// BEGIN INCLUDED FILES
/* The difference between zend_symtable_X and zend_hash_X is that
 * the _symtable version will check if the key is a string of an
 * integer, and if so, use the int version instead. We can use the
 * zend_hash_X versions safely for symbol tables, since
 * variables cant be integer strings, but we cant safely use
 * zend_hash_X versions for hashtable lookups. Well-named, they are.
 */

/* An important note of zval*s and zval**s. Frequently, zval** are
 * fetched from arrays and symbol tables. The zval** will point into
 * the array, and so updating it will update the relevant array
 * entry. It is normally not the same to dereference it to a local
 * variable, and pass a reference to that.
 */



// Some common functions
#include "php.h"

/*
 * The runtime needs its own initialization and finalization.  phc is
 * responsible for generating calls to these functions.
 */

void
init_runtime ()
{
}

void
finalize_runtime ()
{
}

static void
ht_debug (HashTable * ht)
{
  printf ("\nHASH\n");
  if (ht == NULL)
    {
      printf ("NULL\n");
      return;
    }
  for (zend_hash_internal_pointer_reset (ht);
       zend_hash_has_more_elements (ht) == SUCCESS;
       zend_hash_move_forward (ht))
    {
      char *key;
      unsigned keylen;
      unsigned long idx;
      int type;
      zval **ppzval;
      zval *zvp;

      type = zend_hash_get_current_key_ex (ht, &key, &keylen, &idx, 0, NULL);
      zend_hash_get_current_data (ht, (void **) &ppzval);

      zvp = *ppzval;

      if (type == HASH_KEY_IS_STRING)
	{
	  printf ("%s", key);
	}
      else
	{
	  printf ("%ld", idx);
	}

      printf (": addr = %08lX, refcount = %d, is_ref = %d ",
	      (long unsigned int) (*ppzval), (*ppzval)->refcount,
	      (*ppzval)->is_ref);
      switch (Z_TYPE_P (zvp))
	{
	case IS_NULL:
	  printf ("(NULL)");
	  break;
	case IS_LONG:
	  printf ("(%ldL)", Z_LVAL_P (zvp));
	  break;
	case IS_DOUBLE:
	  printf ("(%lff)", Z_DVAL_P (zvp));
	  break;
	case IS_BOOL:
	  printf (Z_BVAL_P (zvp) ? "(true)" : "(false)");
	  break;
	case IS_ARRAY:
	  printf ("(array(%d))", Z_ARRVAL_P (zvp)->nNumOfElements);
	  break;
	case IS_OBJECT:
	  printf ("(Object)");
	  break;
	case IS_STRING:
	  printf ("(\"%s\")", Z_STRVAL_P (zvp));
	  break;
	case IS_RESOURCE:
	  printf ("(Resource)");
	  break;
	default:
	  printf ("(Invalid: %d)", Z_TYPE_P (zvp));
	}

      printf ("\n");

    }
  printf ("END HASH\n");
}

// Call ht_debug on the named var in the given symbol table
static void
ht_var_debug (HashTable * st, char *name)
{
  zval **p_zvp;
  if (zend_symtable_find (st, name, strlen (name) + 1,
			  (void **) &p_zvp) != SUCCESS)
    {
      printf ("VAR NOT IN SYMBOL TABLE: '%s'\n", name);
      return;
    }

  if (Z_TYPE_P (*p_zvp) != IS_ARRAY)
    {
      printf ("NOT HASH\n");
      return;
    }

  ht_debug ((*p_zvp)->value.ht);
}

static zval* counters;

static void init_counters ()
{
  ALLOC_INIT_ZVAL (counters);
  array_init (counters);
}

// Dump and cleanup memory
static void finalize_counters ()
{
  HashTable* ht = Z_ARRVAL_P (counters);
  for (zend_hash_internal_pointer_reset (ht);
       zend_hash_has_more_elements (ht) == SUCCESS;
       zend_hash_move_forward (ht))
    {
      char *key;
      zval **p_zvp;

      zend_hash_get_current_key_ex (ht, &key, NULL, NULL, 0, NULL);
      zend_hash_get_current_data (ht, (void **) &p_zvp);

      fprintf (stderr, "COUNTER:%s:%ld\n", key, Z_LVAL_P (*p_zvp));
    }

  zval_ptr_dtor (&counters);
}

static void increment_counter (char* name, int length, ulong hashval)
{
  zval** p_zvp;
  int success = zend_hash_quick_find (Z_ARRVAL_P (counters),
				      name,
				      length,
				      hashval,
				      (void **) &p_zvp);

  if (success == SUCCESS)
    {
      Z_LVAL_PP (p_zvp)++;
    }
  else
    {

      zval* new_val;
      ALLOC_INIT_ZVAL (new_val);
      ZVAL_LONG (new_val, 1);

      zend_hash_quick_add (Z_ARRVAL_P (counters),
			   name,
			   length,
			   hashval,
			   &new_val,
			   sizeof (zval *),
			   NULL);
    }
}



/* Make a copy of *P_ZVP, storing it in *P_ZVP. */
static zval *
zvp_clone_ex (zval * zvp)
{
  // TODO: use INIT_PZVAL_COPY
  zval *clone;
  MAKE_STD_ZVAL (clone);
  clone->value = zvp->value;
  clone->type = zvp->type;
  zval_copy_ctor (clone);
  return clone;
}


static inline int
in_copy_on_write (zval * zvp)
{
  return (zvp->refcount > 1 && !zvp->is_ref);
}

static inline int
in_change_on_write (zval * zvp)
{
  return (zvp->refcount > 1 && zvp->is_ref);
}

/* If *P_ZVP is in a copy-on-write set, separate it by overwriting
 * *P_ZVP with a clone of itself, and lowering the refcount on the
 * original. */
static void
sep_copy_on_write (zval ** p_zvp)
{
  if (!in_copy_on_write (*p_zvp))
    return;

  zval *old = *p_zvp;

  *p_zvp = zvp_clone_ex (*p_zvp);

  zval_ptr_dtor (&old);
}

/* If *P_ZVP is in a copy-on-write set, separate it by overwriting
 * *P_ZVP with a clone of itself, and lowering the refcount on the
 * original. */
static void
sep_change_on_write (zval ** p_zvp)
{
  assert (in_change_on_write (*p_zvp));

  zval *old = *p_zvp;

  *p_zvp = zvp_clone_ex (*p_zvp);

  zval_ptr_dtor (&old);
}

/* Assign RHS into LHS, by reference. After this, LHS will point to the same
 * zval* as RHS. */
static void
copy_into_ref (zval ** lhs, zval ** rhs)
{
  (*rhs)->is_ref = 1;
  (*rhs)->refcount++;
  zval_ptr_dtor (lhs);
  *lhs = *rhs;
}


// Overwrite one zval with another
static void
overwrite_lhs (zval * lhs, zval * rhs)
{
  // First, call the destructor to remove any data structures
  // associated with lhs that will now be overwritten
  zval_dtor (lhs);
  // Overwrite LHS
  lhs->value = rhs->value;
  lhs->type = rhs->type;
  zval_copy_ctor (lhs);
}

// Overwrite one zval with another
static void
overwrite_lhs_no_copy (zval * lhs, zval * rhs)
{
  // First, call the destructor to remove any data structures
  // associated with lhs that will now be overwritten
  zval_dtor (lhs);
  // Overwrite LHS
  lhs->value = rhs->value;
  lhs->type = rhs->type;
}

/* Write P_RHS into the symbol table as a variable named VAR_NAME. */
// NOTE: We do not alter p_rhs's refcount, unless p_lhs joins its
// Copy-on-write set.
// TODO: this is crying out to be inlined.
static void
write_var (zval ** p_lhs, zval * rhs)
{
  if (!(*p_lhs)->is_ref)
    {
      zval_ptr_dtor (p_lhs);
      // Take a copy of RHS for LHS.
      if (rhs->is_ref)
	{
	  *p_lhs = zvp_clone_ex (rhs);
	}
      else			// share a copy
	{
	  rhs->refcount++;
	  *p_lhs = rhs;
	}
    }
  else
    {
      overwrite_lhs (*p_lhs, rhs);
    }
}

// TODO: this functino does too much, and much might be redundant
static zval **
get_st_entry (HashTable * st, char *name, int length, ulong hashval TSRMLS_DC)
{
  zval **p_zvp;
  if (zend_hash_quick_find
      (st, name, length, hashval, (void **) &p_zvp) == SUCCESS)
    {
      assert (p_zvp != NULL);
      return p_zvp;
    }

  // If we dont find it, put EG (uninitialized_zval_ptr) into the
  // hashtable, and return a pointer to its container.
  EG (uninitialized_zval_ptr)->refcount++;
  int result = zend_hash_quick_add (st, name, length, hashval,
				    &EG (uninitialized_zval_ptr),
				    sizeof (zval *), (void **) &p_zvp);
  assert (result == SUCCESS);
  assert (p_zvp != NULL);

  return p_zvp;
}

/* Read the variable named VAR_NAME from the local symbol table and
 * return it. If the variable doent exist, a new one is created and
 * *IS_NEW is set.  */
static zval *
read_var (HashTable * st, char *name, int length, ulong hashval TSRMLS_DC)
{
  zval **p_zvp;
  if (zend_hash_quick_find
      (st, name, length, hashval, (void **) &p_zvp) == SUCCESS)
    return *p_zvp;

  return EG (uninitialized_zval_ptr);
}

static long
get_integer_index (zval * ind TSRMLS_DC)
{
  long index;
  switch (Z_TYPE_P (ind))
    {
    case IS_DOUBLE:
      return (long) Z_DVAL_P (ind);

    case IS_LONG:
    case IS_BOOL:
      return Z_LVAL_P (ind);

    case IS_NULL:
      return 0;

    default:
      php_error_docref (NULL TSRMLS_CC, E_WARNING, "Illegal offset type");
    }
}

static zval *
read_string_index (zval * var, zval * ind TSRMLS_DC)
{
  // This must always allocate memory, since we cant return the
  // passed string.
  assert (Z_TYPE_P (var) == IS_STRING);
  long index = get_integer_index (ind TSRMLS_CC);

  zval *result;
  ALLOC_INIT_ZVAL (result);

  if (index >= Z_STRLEN_P (var) || index < 0)
    {
      // this is 1 byte long, must be copied
      ZVAL_STRINGL (result, "", 0, 1);
    }
  else
    {
      char *string = Z_STRVAL_P (var);
      ZVAL_STRINGL (result, &string[index], 1, 1);
    }

  return result;
}

/* Given a string (p_lhs), write into it for $x[i] = $y; */
void
write_string_index (zval ** p_lhs, zval * ind, zval * rhs TSRMLS_DC)
{
  assert (Z_TYPE_P (*p_lhs) == IS_STRING);

  long index = get_integer_index (ind TSRMLS_CC);

  // Get the appropriate character
  char new_char;
  if (Z_TYPE_P (rhs) != IS_STRING)
    {
      // TODO: remove allocate
      zval *copy = zvp_clone_ex (rhs);
      convert_to_string (copy);
      new_char = Z_STRVAL_P (copy)[0];
      zval_ptr_dtor (&copy);
    }
  else
    {
      new_char = Z_STRVAL_P (rhs)[0];
    }

  // Bounds check
  if (index < 0)
    {
      php_error_docref (NULL TSRMLS_CC, E_WARNING,
			"Illegal string offset:  %ld", index);
      return;
    }

  // We overwrite if it's change-on-write
  sep_copy_on_write (p_lhs);

  if (index > Z_STRLEN_PP (p_lhs))
    {
      // Extend to fix new
      int len = Z_STRLEN_PP (p_lhs);
      int new_length = index + 1;	// space for the new character
      Z_STRVAL_PP (p_lhs) = erealloc (Z_STRVAL_PP (p_lhs), new_length + 1);

      // pad with ' '
      memset (&Z_STRVAL_PP (p_lhs)[len], ' ', index - len);

      // change the strlen
      Z_STRLEN_PP (p_lhs) = new_length;

      // add a null terminator
      Z_STRVAL_PP (p_lhs)[new_length] = '\0';
    }

  // write in the first character of the new value
  Z_STRVAL_PP (p_lhs)[index] = new_char;


  // index < 0: E_WARNING illegal string offset
}

// Extract the hashtable from a hash-valued zval
static HashTable *
extract_ht_ex (zval * arr TSRMLS_DC)
{
  // TODO: this likely should be inlined somewhere.
  assert (!in_copy_on_write (arr));
  if (Z_TYPE_P (arr) == IS_NULL)
    {
      array_init (arr);
    }
  else if (Z_TYPE_P (arr) != IS_ARRAY)
    {
      php_error_docref (NULL TSRMLS_CC, E_WARNING,
			"Cannot use a scalar value as an array");
      array_init (arr);
    }
  return Z_ARRVAL_P (arr);
}


/* P_VAR points into a symbol table, at a variable which we wish to index as a hashtable. */
static HashTable *
extract_ht (zval ** p_var TSRMLS_DC)
{
  sep_copy_on_write (p_var);

  return extract_ht_ex (*p_var TSRMLS_CC);
}

/* Using IND as a key to HT, call the appropriate zend_index_X
 * function with data as a parameter, and return its result. This
 * updates the zval** pointed to by DATA. */
static int
ht_find (HashTable * ht, zval * ind, zval *** data)
{
  int result;
  if (Z_TYPE_P (ind) == IS_LONG || Z_TYPE_P (ind) == IS_BOOL)
    {
      result = zend_hash_index_find (ht, Z_LVAL_P (ind), (void **) data);
    }
  else if (Z_TYPE_P (ind) == IS_DOUBLE)
    {
      result = zend_hash_index_find (ht, (long) Z_DVAL_P (ind),
				     (void **) data);
    }
  else if (Z_TYPE_P (ind) == IS_NULL)
    {
      result = zend_hash_find (ht, "", sizeof (""), (void **)data);
    }
  else if (Z_TYPE_P (ind) == IS_STRING)
    {
      result = zend_symtable_find (ht, Z_STRVAL_P (ind),
				   Z_STRLEN_P (ind) + 1, (void **) data);
    }
  else
    {
      // TODO: I believe this might need a warning.

      // TODO avoid alloc
      // use a string index for other types
      zval *string_index;
      MAKE_STD_ZVAL (string_index);
      string_index->value = ind->value;
      string_index->type = ind->type;
      zval_copy_ctor (string_index);
      convert_to_string (string_index);

      result = zend_symtable_find (ht, Z_STRVAL_P (string_index),
				   Z_STRLEN_P (string_index) + 1,
				   (void **) data);
      zval_ptr_dtor (&string_index);
    }
  return result;
}


static int
check_array_index_type (zval * ind TSRMLS_DC)
{
  if (Z_TYPE_P (ind) == IS_OBJECT || Z_TYPE_P (ind) == IS_ARRAY)
    {
      php_error_docref (NULL TSRMLS_CC, E_WARNING, "Illegal offset type");
      return 0;
    }

  return 1;
}

// Update a hashtable using a zval* index
static void
ht_update (HashTable * ht, zval * ind, zval * val, zval *** dest)
{
  int result;
  if (Z_TYPE_P (ind) == IS_LONG || Z_TYPE_P (ind) == IS_BOOL)
    {
      result = zend_hash_index_update (ht, Z_LVAL_P (ind), &val,
				       sizeof (zval *), (void **) dest);
    }
  else if (Z_TYPE_P (ind) == IS_DOUBLE)
    {
      result = zend_hash_index_update (ht, (long) Z_DVAL_P (ind),
				       &val, sizeof (zval *), (void **) dest);
    }
  else if (Z_TYPE_P (ind) == IS_NULL)
    {
      result = zend_hash_update (ht, "", sizeof (""), &val,
				 sizeof (zval *), (void **) dest);
    }
  else if (Z_TYPE_P (ind) == IS_STRING)
    {
      result = zend_symtable_update (ht, Z_STRVAL_P (ind),
				     Z_STRLEN_P (ind) + 1,
				     &val, sizeof (zval *), (void **) dest);
    }
  else
    {
      // TODO avoid alloc
      zval *string_index;
      MAKE_STD_ZVAL (string_index);
      string_index->value = ind->value;
      string_index->type = ind->type;
      zval_copy_ctor (string_index);
      convert_to_string (string_index);
      result = zend_symtable_update (ht, Z_STRVAL_P (string_index),
				     Z_STRLEN_P (string_index) + 1,
				     &val, sizeof (zval *), (void **) dest);

      zval_ptr_dtor (&string_index);
    }
  assert (result == SUCCESS);
}

// Delete from a hashtable using a zval* index
static void
ht_delete (HashTable * ht, zval * ind)
{
  // This may fail if the index doesnt exist, which is fine.
  if (Z_TYPE_P (ind) == IS_LONG || Z_TYPE_P (ind) == IS_BOOL)
    {
      zend_hash_index_del (ht, Z_LVAL_P (ind));
    }
  else if (Z_TYPE_P (ind) == IS_DOUBLE)
    {
      zend_hash_index_del (ht, (long) Z_DVAL_P (ind));
    }
  else if (Z_TYPE_P (ind) == IS_NULL)
    {
      zend_hash_del (ht, "", sizeof (""));
    }
  else if (Z_TYPE_P (ind) == IS_STRING)
    {
      zend_hash_del (ht, Z_STRVAL_P (ind), Z_STRLEN_P (ind) + 1);
    }
  else
    {
      // TODO avoid alloc
      zval *string_index;
      MAKE_STD_ZVAL (string_index);
      string_index->value = ind->value;
      string_index->type = ind->type;
      zval_copy_ctor (string_index);
      convert_to_string (string_index);
      zend_hash_del (ht, Z_STRVAL_P (string_index),
		     Z_STRLEN_P (string_index) + 1);

      zval_ptr_dtor (&string_index);
    }
}

// Check if a key exists in a hashtable 
static int
ht_exists (HashTable * ht, zval * ind)
{
  if (Z_TYPE_P (ind) == IS_LONG || Z_TYPE_P (ind) == IS_BOOL)
    {
      return zend_hash_index_exists (ht, Z_LVAL_P (ind));
    }
  else if (Z_TYPE_P (ind) == IS_DOUBLE)
    {
      return zend_hash_index_exists (ht, (long) Z_DVAL_P (ind));
    }
  else if (Z_TYPE_P (ind) == IS_NULL)
    {
      return zend_hash_exists (ht, "", sizeof (""));
    }
  else if (Z_TYPE_P (ind) == IS_STRING)
    {
      return zend_hash_exists (ht, Z_STRVAL_P (ind), Z_STRLEN_P (ind) + 1);
    }
  else
    {
      // TODO avoid alloc
      int result;
      zval *string_index;
      MAKE_STD_ZVAL (string_index);
      string_index->value = ind->value;
      string_index->type = ind->type;
      zval_copy_ctor (string_index);
      convert_to_string (string_index);
      result = zend_hash_exists (ht, Z_STRVAL_P (string_index),
				 Z_STRLEN_P (string_index) + 1);
      zval_ptr_dtor (&string_index);
      return result;
    }
  assert (0);
}

static zval **
get_ht_entry (zval ** p_var, zval * ind TSRMLS_DC)
{
  if (Z_TYPE_P (*p_var) == IS_STRING)
    {
      if (Z_STRLEN_PP (p_var) > 0)
	{
	  php_error_docref (NULL TSRMLS_CC, E_ERROR,
			    "Cannot create references to/from string offsets nor overloaded objects");
	}
    }

  if (Z_TYPE_P (*p_var) != IS_ARRAY)
    {
      zval_ptr_dtor (p_var);
      ALLOC_INIT_ZVAL (*p_var);
      array_init (*p_var);
    }

  HashTable *ht = extract_ht (p_var TSRMLS_CC);

  zval **data;
  if (ht_find (ht, ind, &data) == SUCCESS)
    {
      assert (data != NULL);
      return data;
    }

  // If we dont find it, put EG (uninitialized_zval_ptr) into the
  // hashtable, and return a pointer to its container.
  EG (uninitialized_zval_ptr)->refcount++;
  ht_update (ht, ind, EG (uninitialized_zval_ptr), &data);

  assert (data != NULL);

  return data;
}


// Like extract_ht_ex, but for objects 
static HashTable *
extract_field_ex (zval * obj TSRMLS_DC)
{
  // TODO: this likely should be inlined somewhere.
  assert (!in_copy_on_write (obj));
  if (Z_TYPE_P (obj) == IS_NULL)
    {
      assert (0);
      // TODO: implement initialization
    }
  else if (Z_TYPE_P (obj) != IS_OBJECT)
    {
      // TODO: test if this is the right error message
      php_error_docref (NULL TSRMLS_CC, E_WARNING,
			"Cannot use a scalar value as an object");
      // TODO: implement initialization
      assert (0);
    }
  return Z_OBJPROP_P (obj);
}

// Like extract_ht, but for objects
static HashTable *
extract_field (zval ** p_var TSRMLS_DC)
{
  sep_copy_on_write (p_var);

  return extract_field_ex (*p_var TSRMLS_CC);
}

// Like get_ht_entry, but for objects
static zval **
get_field (zval ** p_var, char *ind TSRMLS_DC)
{
  if (Z_TYPE_P (*p_var) != IS_OBJECT)
    {
      // TODO: implement initialization
      assert (0);
    }

  HashTable *ht = extract_field (p_var TSRMLS_CC);

  zval **data;
  if (zend_symtable_find (ht, ind, strlen (ind) + 1, (void **) &data) ==
      SUCCESS)
    {
      assert (data != NULL);
      return data;
    }

  // If we dont find it, put EG (uninitialized_zval_ptr) into the
  // hashtable, and return a pointer to its container.
  EG (uninitialized_zval_ptr)->refcount++;
  zend_symtable_update (ht, ind, strlen (ind) + 1,
			&EG (uninitialized_zval_ptr), sizeof (zval *),
			(void **) &data);

  assert (data != NULL);

  return data;
}

void
read_array (zval ** result, zval * array, zval * ind TSRMLS_DC)
{
  // Memory can be allocated in read_string_index
  if (array == EG (uninitialized_zval_ptr))
    {
      *result = array;
      return;
    }

  // Since we know its an array, and we dont write to it, we dont need
  // to separate it.
  HashTable *ht = Z_ARRVAL_P (array);

  // find the result
  zval **p_result;
  if (ht_find (ht, ind, &p_result) == SUCCESS)
    {
      *result = *p_result;
      return;
    }

  *result = EG (uninitialized_zval_ptr);
}

/* If its not an array, convert it into an array. */
static void
check_array_type (zval ** p_var TSRMLS_DC)
{
  if ((Z_TYPE_P (*p_var) == IS_BOOL && !Z_BVAL_PP (p_var))
      || Z_TYPE_P (*p_var) == IS_NULL
      || (Z_TYPE_P (*p_var) == IS_STRING && Z_STRLEN_PP (p_var) == 0))
    {
      // Non ref use new values
      if (!PZVAL_IS_REF (*p_var))
	{
	  zval_ptr_dtor (p_var);
	  ALLOC_INIT_ZVAL (*p_var);
	}
      else
	// Refs are just replaced
	zval_dtor (*p_var);

      array_init (*p_var);
    }
  else if (Z_TYPE_PP (p_var) != IS_STRING && Z_TYPE_PP (p_var) != IS_ARRAY)
    {
      // TODO: why are these different types than pushing
      php_error_docref (NULL TSRMLS_CC, E_WARNING,
			"Cannot use a scalar value as an array");
    }
}

/* If its not an array, convert it into an object. */
static void
check_object_type (zval ** p_var TSRMLS_DC)
{
  // TODO: implement
}

/* Push EG (uninitialized_zval_ptr) and return a pointer into the ht
 * for it */
/*
 * Converted to array automatically:
 *    ""
 *    NULL
 *    false
 *
 * Warning, no conversion:
 *    ints
 *    floats
 *    true
 *
 * Error, no conversion:
 *    strings other than ""
 */
// TODO: objects, resources, etc
static zval **
push_and_index_ht (zval ** p_var TSRMLS_DC)
{
  // Check for errors conditions

  if (Z_TYPE_P (*p_var) == IS_STRING && Z_STRLEN_PP (p_var) > 0)
    {
      php_error_docref (NULL TSRMLS_CC, E_ERROR,
			"[] operator not supported for strings");
      assert (0);		// unreachable
    }

  if (Z_TYPE_P (*p_var) == IS_BOOL && Z_BVAL_PP (p_var)
      || Z_TYPE_P (*p_var) == IS_LONG || Z_TYPE_P (*p_var) == IS_DOUBLE)
    {
      php_error_docref (NULL TSRMLS_CC, E_WARNING,
			"Cannot use a scalar value as an array");
      return NULL;
    }

  if (Z_TYPE_P (*p_var) != IS_ARRAY)
    {
      zval_ptr_dtor (p_var);
      ALLOC_INIT_ZVAL (*p_var);
      array_init (*p_var);
    }

  // if its not an array, make it an array
  HashTable *ht = extract_ht (p_var TSRMLS_CC);
  zval **data;

  EG (uninitialized_zval_ptr)->refcount++;
  int result = zend_hash_next_index_insert (ht, &EG (uninitialized_zval_ptr),
					    sizeof (zval *), (void **) &data);
  assert (result == SUCCESS);

  assert (data);

  return data;
}


/*
 * isset
 */
static int
isset_var (HashTable * st, char *name, int length)
{
  return zend_hash_exists (st, name, length);
}

static int
isset_array (zval ** p_var, zval * ind)
{
  if (Z_TYPE_P (*p_var) == IS_STRING)
    {
      ind = zvp_clone_ex (ind);
      convert_to_long (ind);
      int result = (Z_LVAL_P (ind) >= 0
		    && Z_LVAL_P (ind) < Z_STRLEN_PP (p_var));
      assert (ind->refcount == 1);
      zval_ptr_dtor (&ind);
      return result;
    }

  // NO error required; return false
  if (Z_TYPE_P (*p_var) != IS_ARRAY)
    return 0;

  // if its not an array, make it an array
  HashTable *ht = Z_ARRVAL_P (*p_var);

  zval **data;
  if (ht_find (ht, ind, &data) == SUCCESS)
    {
      return !ZVAL_IS_NULL (*data);
    }
  else
    return 0;
}


static zval **
fetch_var_arg_by_ref (zval ** p_arg)
{
  // We are passing by reference
  sep_copy_on_write (p_arg);

  // We don't need to restore ->is_ref afterwards,
  // because the called function will reduce the
  // refcount of arg on return, and will reset is_ref to
  // 0 when refcount drops to 1.  If the refcount does
  // not drop to 1 when the function returns, but we did
  // set is_ref to 1 here, that means that is_ref must
  // already have been 1 to start with (since if it had
  // not, that means that the variable would have been
  // in a copy-on-write set, and would have been
  // seperated above).
  (*p_arg)->is_ref = 1;

  return p_arg;
}

/* Dont pass-by-ref */
static zval *
fetch_var_arg (zval * arg, int *is_arg_new)
{
  if (arg->is_ref)
    {
      // We dont separate since we don't own one of ARG's references.
      arg = zvp_clone_ex (arg);
      *is_arg_new = 1;

      // It seems we get incorrect refcounts without this.
      // TODO This decreases the refcount to zero, which seems wrong,
      // but gives the right answer. We should look at how zend does
      // this.

      arg->refcount--;
    }
  return arg;
}

// TODO dont overwrite line numbers if we're compiling an extension
static void
phc_setup_error (int init, char *filename, int line_number,
		 zend_function * function TSRMLS_DC)
{
  static int old_in_compilation;
  static int old_in_execution;
  static char *old_filename;
  static int old_lineno;
  static zend_function *old_function;
  if (init)
    {
      if (filename == NULL)
	filename = "[phc_compiled_file]";
      // Save old values
      old_in_compilation = CG (in_compilation);
      old_in_execution = EG (in_execution);
      old_filename = CG (compiled_filename);
      old_lineno = CG (zend_lineno);
      old_function = EG (function_state_ptr)->function;
      // Put in our values
      CG (in_compilation) = 1;
      EG (in_execution) = 1;
      CG (compiled_filename) = filename;
      CG (zend_lineno) = line_number;
      if (function)
	EG (function_state_ptr)->function = function;
    }
  else
    {
      CG (in_compilation) = old_in_compilation;
      EG (in_execution) = old_in_execution;
      CG (compiled_filename) = old_filename;
      CG (zend_lineno) = old_lineno;
      EG (function_state_ptr)->function = old_function;
    }
}

static void
initialize_function_call (zend_fcall_info * fci, zend_fcall_info_cache * fcic,
			  char *function_name, char *filename,
			  int line_number TSRMLS_DC)
{
  if (fcic->initialized)
    return;

  zval fn;
  INIT_PZVAL (&fn);
  ZVAL_STRING (&fn, function_name, 0);
  int result = zend_fcall_info_init (&fn, fci, fcic TSRMLS_CC);
  if (result != SUCCESS)
    {
      phc_setup_error (1, filename, line_number, NULL TSRMLS_CC);
      php_error_docref (NULL TSRMLS_CC, E_ERROR,
			"Call to undefined function %s()", function_name);
    }
}

/*
 * Initialize zend_fcall_info for a method lookup
 *
 * Implementation partly based on zend_call_method in Zend/zend_interfaces.c
 * Main difference is that we use Z_OBJ_HTT_PP(obj)->get_method to retrieve
 * the function handler for the method instead of looking it up directly;
 * this means that we correctly deal with __call.
 */

static void
initialize_method_call (zend_fcall_info * fci, zend_fcall_info_cache * fcic,
			zval ** obj, char *function_name,
			char *filename, int line_number TSRMLS_DC)
{
  if (fcic->initialized)
    return;

  zend_class_entry *obj_ce;
  obj_ce = Z_OBJCE_PP (obj);

  /*
   * we do not initialize fci.
   *   function_table  --  not initialized by zend_call_method
   *   function_name   --  zend_call_method initializes this to a pointer to
   *                       a zval 'z_fname', but does not initialize z_fname
   *                       in case of a method invocation
   *   retval_ptr_ptr  --  should be initialized by caller
   *   param_count     --  should be initialized by caller
   *   params          --  should be initialized by caller
   */
  fci->size = sizeof (*fci);
  fci->object_pp = obj;
  fci->no_separation = 1;
  fci->symbol_table = NULL;

  fcic->initialized = 1;
  fcic->calling_scope = obj_ce;
  fcic->object_pp = obj;
  fcic->function_handler
    = Z_OBJ_HT_PP (obj)->get_method (obj,
				     function_name,
				     strlen (function_name) TSRMLS_CC);

  if (fcic->function_handler == NULL)
    {
      phc_setup_error (1, filename, line_number, NULL TSRMLS_CC);
      php_error_docref (NULL TSRMLS_CC, E_ERROR,
			"Call to undefined method %s::%s",
			obj_ce->name, function_name);
    }
}

/*
 * Like initialize_method_call, but return 0 if no constructor is defined
 * rather than giving an error.
 */

static int 
initialize_constructor_call (zend_fcall_info * fci,
			     zend_fcall_info_cache * fcic, zval ** obj,
			     char *filename, int line_number TSRMLS_DC)
{
  if (fcic->initialized)
    return;

  zend_class_entry *obj_ce;
  obj_ce = Z_OBJCE_PP (obj);

  /*
   * we do not initialize fci.
   *   function_table  --  not initialized by zend_call_method
   *   function_name   --  zend_call_method initializes this to a pointer to
   *                       a zval 'z_fname', but does not initialize z_fname
   *                       in case of a method invocation
   *   retval_ptr_ptr  --  should be initialized by caller
   *   param_count     --  should be initialized by caller
   *   params          --  should be initialized by caller
   */
  fci->size = sizeof (*fci);
  fci->object_pp = obj;
  fci->no_separation = 1;
  fci->symbol_table = NULL;

  fcic->initialized = 1;
  fcic->calling_scope = obj_ce;
  fcic->object_pp = obj;
  fcic->function_handler
    = Z_OBJ_HT_PP (obj)->get_constructor (*obj TSRMLS_CC);

  return (fcic->function_handler != NULL);
}
// vi:set ts=8:

/*
 * Creates a copy of *in using persistent memory, optionally destroying *in
 *
 * Does not work for objects/resources and will loop on self-recursive arrays.
 */

zval *
persistent_clone (zval * in, int destroy_in TSRMLS_DC)
{
  zval *out = pemalloc (sizeof (zval), 1);
  *out = *in;

  switch (Z_TYPE_P (in))
    {
    case IS_NULL:
    case IS_LONG:
    case IS_DOUBLE:
    case IS_BOOL:
      /* nothing more to be done */
      break;
    case IS_STRING:
      Z_STRVAL_P (out) = pemalloc (Z_STRLEN_P (in) + 1, 1);
      memcpy (Z_STRVAL_P (out), Z_STRVAL_P (in), Z_STRLEN_P (in) + 1);
      break;
    case IS_ARRAY:
      {
	HashTable *old_arr = Z_ARRVAL_P (in);
	HashTable *new_arr = pemalloc (sizeof (HashTable), 1);
	zend_hash_init (new_arr, old_arr->nNumOfElements, NULL, ZVAL_PTR_DTOR,
			/* persistent */ 1);

	for (zend_hash_internal_pointer_reset (old_arr);
	     zend_hash_has_more_elements (old_arr) == SUCCESS;
	     zend_hash_move_forward (old_arr))
	  {
	    char *key;
	    uint keylen;
	    ulong idx;
	    int type;
	    zval **old_elem, *new_elem;

	    type =
	      zend_hash_get_current_key_ex (old_arr, &key, &keylen, &idx, 0,
					    NULL);
	    assert (zend_hash_get_current_data
		    (old_arr, (void **) &old_elem) == SUCCESS);

	    new_elem = persistent_clone (*old_elem, destroy_in TSRMLS_CC);

	    if (type == HASH_KEY_IS_STRING)
	      zend_hash_add (new_arr, key, keylen, &new_elem, sizeof (zval *),
			     NULL);
	    else
	      zend_hash_index_update (new_arr, idx, &new_elem,
				      sizeof (zval *), NULL);

	  }

	Z_ARRVAL_P (out) = new_arr;
      }
      break;
    default:
      /* other types are not supported */
      assert (0);
    }

  zval_ptr_dtor (&in);
  return out;
}

/*
 * Wrapper around zend_declare_property which 
 *
 * - Asserts that the ZEND_INTERNAL_CLASS flag is cleared
 *   (otherwise we cannot add complex (i.e., array) properties)
 * - Creates a persistent clone of the property to be added before
 *   calling zend_declare_property, since the memory for this property
 *   should only be deallocated when the module is shut down
 *   (and not when the request finishes)
 * - Cleans up after zend_declare_property by re-allocating the name of 
 *   the property using persistent memory, for much the same reason
 */

static int
phc_declare_property (zend_class_entry * ce, char *name, int name_length,
		      zval * property, int access_type TSRMLS_DC)
{
  assert (!(ce->type & ZEND_INTERNAL_CLASS));
  assert (zend_declare_property
	  (ce, name, name_length, persistent_clone (property, 1 TSRMLS_CC),
	   access_type TSRMLS_CC) == SUCCESS);

  zend_property_info *property_info;
  assert (zend_hash_find
	  (&ce->properties_info, name, name_length + 1,
	   (void **) &property_info) == SUCCESS);
  efree (property_info->name);
  property_info->name = name;

  return SUCCESS;
}

// vi:set ts=8:


static void
cast_var (zval ** p_zvp, int type)
{
  assert (type >= 0 && type <= 6);
  if ((*p_zvp)->type == type)
    return;

  sep_copy_on_write (p_zvp);
  zval *zvp = *p_zvp;

  switch (type)
    {
    case IS_NULL:
      convert_to_null (zvp);
      break;
    case IS_BOOL:
      convert_to_boolean (zvp);
      break;
    case IS_LONG:
      convert_to_long (zvp);
      break;
    case IS_DOUBLE:
      convert_to_double (zvp);
      break;
    case IS_STRING:
      convert_to_string (zvp);
      break;
    case IS_ARRAY:
      convert_to_array (zvp);
      break;
    case IS_OBJECT:
      convert_to_object (zvp);
      break;
    default:
      assert (0);		// TODO unimplemented
      break;
    }
}

/* Copies a constant into ZVP. Note that LENGTH does not include the NULL-terminating byte. */
static void
get_constant (char *name, int length, zval ** p_zvp TSRMLS_DC)
{
  MAKE_STD_ZVAL (*p_zvp);
  // zend_get_constant returns 1 for success, not SUCCESS
  int result = zend_get_constant (name, length, *p_zvp TSRMLS_CC);
  if (result == 0)
    ZVAL_STRINGL (*p_zvp, name, length, 1);
}

/* The function call mechanism deals specially with EG(uninitialize_zval_ptr)
 * (or sometime EG(uninitialize_zval)), so we need to use this too. This
 * particular zval can also be set, but there is an implicit guarantee 
 * of the information below.
 *
 * If assertions are off, this should be inlined to nothing.
 */
static void
phc_check_invariants (TSRMLS_D)
{
  assert (EG (uninitialized_zval_ptr) == &EG (uninitialized_zval));
  assert (EG (uninitialized_zval).refcount >= 1);
  assert (EG (uninitialized_zval).value.lval == 0);
  assert (EG (uninitialized_zval).type == IS_NULL);
  assert (EG (uninitialized_zval).is_ref == 0);
}


static int
check_unset_index_type (zval * ind TSRMLS_DC)
{
  if (Z_TYPE_P (ind) == IS_OBJECT || Z_TYPE_P (ind) == IS_ARRAY)
    {
      php_error_docref (NULL TSRMLS_CC, E_WARNING,
			"Illegal offset type in unset");
      return 0;
    }

  return 1;
}



/*
 * unset
 */

static void
unset_var (HashTable * st, char *name, int length)
{
  zend_hash_del (st, name, length);
}

static void
unset_array (zval ** p_var, zval * ind TSRMLS_DC)
{
  // NO error required
  if (Z_TYPE_PP (p_var) != IS_ARRAY)
    {
      if (Z_TYPE_PP (p_var) == IS_STRING)
	{
	  php_error_docref (NULL TSRMLS_CC, E_ERROR,
			    "Cannot unset string offsets");
	}
      else if (Z_TYPE_PP (p_var) != IS_NULL)
	{
	  php_error_docref (NULL TSRMLS_CC, E_WARNING,
			    "Cannot unset offsets in a non-array variable");
	}

      return;
    }

  // if its not an array, make it an array
  HashTable *ht = Z_ARRVAL_P (*p_var);

  ht_delete (ht, ind);
}

/*
 * Lookup variable whose name is var_var in st. We do not call
 * ht_find because ht_find uses zend_symtable_find to search for strings
 * rather than zend_hash_find. The difference is that zend_symtable_find
 * will convert strings to integers where possible: arrays are always
 * integer-indexed if at all possible. Variable names however should
 * _always_ be treated as strings.
 * 
 */

/*
 * If the parameter is a string, returns the parameter, with the refcount
 * incremented. If its not a string, returns a new zval, with a refcount of
 * 1. Either way, zval_dtor_ptr must be run by the caller on the return
 * value.
 */
zval*
get_string_val (zval* zvp)
{
  if (Z_TYPE_P (zvp) == IS_STRING)
    {
      zvp->refcount++;
      return zvp;
    }
  else
    {
      zval* clone = zvp_clone_ex (zvp);
      convert_to_string (clone);
      return clone;
    }
}

zval **
get_var_var (HashTable * st, zval * index TSRMLS_DC)
{
  zval* str_index = get_string_val (index);
  char* name = Z_STRVAL_P (str_index);
  int length = Z_STRLEN_P (str_index) + 1;
  unsigned long hash = zend_get_hash_value (name, length);

  zval** result = get_st_entry (st, name, length, hash TSRMLS_CC);
  zval_ptr_dtor (&str_index);
  return result;
}

/* 
 * Read the variable described by var_var from symbol table st
 * See comments for get_var_var
 */
zval *
read_var_var (HashTable * st, zval * index TSRMLS_DC)
{
  zval* str_index = get_string_val (index);
  char* name = Z_STRVAL_P (str_index);
  int length = Z_STRLEN_P (str_index) + 1;
  unsigned long hash = zend_get_hash_value (name, length);

  zval* result = read_var (st, name, length, hash TSRMLS_CC);
  zval_ptr_dtor (&str_index);
  return result;
}

static void
phc_builtin_eval (zval * arg, zval ** p_result, char *filename TSRMLS_DC)
{
  // If the user wrote "return ..", we need to store the
  // return value; however, in that case, zend_eval_string
  // will slap an extra "return" onto the front of the string,
  // so we must remove the "return" from the string the user
  // wrote. If the user did not write "return", he is not
  // interested in the return value, and we must pass NULL
  // instead or rhs to avoid zend_eval_string adding "return".

  // convert to a string
  // TODO avoid allocation
  zval *copy = zvp_clone_ex (arg);
  convert_to_string (copy);

  if (*p_result && !strncmp (Z_STRVAL_P (copy), "return ", 7))
    {
      zend_eval_string (Z_STRVAL_P (copy) + 7, *p_result,
			"eval'd code" TSRMLS_CC);
    }
  else
    {
      zend_eval_string (Z_STRVAL_P (copy), NULL, "eval'd code" TSRMLS_CC);
    }

  // cleanup
  assert (copy->refcount == 1);
  zval_ptr_dtor (&copy);
}

static void
phc_builtin_exit (zval * arg, zval ** p_result, char *filename TSRMLS_DC)
{
  if (Z_TYPE_P (arg) == IS_LONG)
    EG (exit_status) = Z_LVAL_P (arg);
  else
    zend_print_variable (arg);

  zend_bailout ();
}

static void
phc_builtin_die (zval * arg, zval ** p_result, char *filename TSRMLS_DC)
{
  phc_builtin_exit (arg, p_result, filename TSRMLS_CC);
}

static void
phc_builtin_echo (zval * arg, zval ** p_result TSRMLS_DC)
{
  assert (*p_result == NULL);
  zend_print_variable (arg);
}

static void
phc_builtin_print (zval * arg, zval ** p_result, char *filename TSRMLS_DC)
{
  zval *echo_arg = NULL;
  phc_builtin_echo (arg, &echo_arg TSRMLS_CC);

  if (*p_result)
    ZVAL_LONG (*p_result, 1);
}

// TODO is there a memory leak here is result has a value?
// TOOD isnt this just the same as isset
static void
phc_builtin_empty (zval * arg, zval ** p_result, char *filename TSRMLS_DC)
{
  assert (*p_result);
  ZVAL_BOOL (*p_result, !zend_is_true (arg));
}

// For require, include, require_once and include_once.

// Include:
//    return 1 for success
//    Warning, and return false for failure
// Require:
//    return 1 for success
//    Fail for failure
// Include_once
//    Return true if already included
//    Return 1 for success
//    Warning and return false for failure
// Require_once:
//    Return true if already included
//    return 1 for success
//    Fail for failure
//
static void
include_backend (zval * arg, zval ** p_result, char *filename, int type, int is_once, char* error, char* error_function TSRMLS_DC)
{
  // In the event that the Zend engine cannot find the file, after checking the
  // include path, it tries the current directory. It does this only if the
  // interpreter is executing, and it checks the interpreters opcodes for a
  // filename (see streams/plain_wrapper.c:1352)

  // An alternative is to add the directory to include_path, but its
  // semantically incorrect (get_included_path() would give the wrong answer),
  // and error prone (if people overwrite include_path).
  // TODO: though we could add it for this function only

  assert (EG (active_op_array) == NULL);
  assert (filename != NULL);

  zval *arg_file = arg;
  // Check we have a string
  if (Z_TYPE_P (arg_file) != IS_STRING)
    {
      arg_file = zvp_clone_ex (arg_file);
      convert_to_string (arg_file);
    }

  zend_file_handle handle;
  zend_op_array* new_op_array;
  zend_function zf;

  // Check the _ONCE varieties (based on zend_vm_def.h)
   if (is_once)
     {
       if (IS_ABSOLUTE_PATH (Z_STRVAL_P (arg_file), Z_STRLEN_P (arg_file)))
	 {
	   // Get the proper path name for require
	   cwd_state state;

	   state.cwd_length = 0;
	   state.cwd = malloc(1);
	   state.cwd[0] = 0;
	   int success = !virtual_file_ex(&state, Z_STRVAL_P(arg_file), NULL, 1)
	     && zend_hash_exists(&EG(included_files), state.cwd,
				 state.cwd_length+1);

	   free (state.cwd);

	   if (!success)
	     goto cleanup;
	 }
     }


   // Compile the file
   // Pretend the interpreter is running
   EG (in_execution) = 1;

   int success = zend_stream_open (Z_STRVAL_P (arg_file), &handle TSRMLS_CC);

   // Stop pretending
   EG (in_execution) = 0;
   EG (active_op_array) = NULL;

   if (success != SUCCESS)
     goto fail;


   if (is_once)
     {
       // Check it hadnt been included already
       int once_success = zend_hash_add_empty_element(&EG(included_files),
						      handle.opened_path,
						      strlen (handle.opened_path)+1);
       // Return true 
       if (once_success != SUCCESS)
	 {
	   ZVAL_BOOL (*p_result, 1);
	   goto cleanup;
	 }
     }

   if (!handle.opened_path)
     handle.opened_path = estrndup (Z_STRVAL_P(arg_file), Z_STRLEN_P (arg_file));

   // run it
   success = zend_execute_scripts (type TSRMLS_CC, p_result, 1, &handle);
   assert (success == SUCCESS);
   zend_stream_close (&handle);

   // Success
   if (*p_result)
       ZVAL_LONG (*p_result, 1);


   goto cleanup;


fail:

   php_error_docref (error_function
		     TSRMLS_CC, 
		     (type == ZEND_INCLUDE) ? E_WARNING : E_ERROR,
		     error,
		     php_strip_url_passwd (Z_STRVAL_P (arg_file)),
		     STR_PRINT (PG (include_path)));


   // Failure
   if (*p_result)
     ZVAL_BOOL (*p_result, 0);

cleanup:

   if (handle.opened_path)
     efree (handle.opened_path);
   zend_destroy_file_handle (&handle TSRMLS_CC);


  if (arg != arg_file)
    zval_ptr_dtor (&arg_file);
}

static void
phc_builtin_include (zval * arg, zval ** p_result, char *filename TSRMLS_DC)
{
  include_backend ( arg,
		    p_result,
		    filename,
		    ZEND_INCLUDE,
		    0,
		    "Failed opening '%s' for inclusion (include_path='%s')",
		    "function.include"
		    TSRMLS_CC);
}

static void
phc_builtin_require (zval * arg, zval ** p_result, char *filename TSRMLS_DC)
{
  include_backend ( arg,
		    p_result,
		    filename,
		    ZEND_REQUIRE,
		    0,
		    "Failed opening required '%s' (include_path='%s')",
		    "function.require"
		    TSRMLS_CC);
}

static void
phc_builtin_include_once (zval * arg, zval ** p_result, char *filename TSRMLS_DC)
{
  include_backend ( arg,
		    p_result,
		    filename,
		    ZEND_INCLUDE,
		    1,
		    "Failed opening '%s' for inclusion (include_path='%s')",
		    "function.include_once"
		    TSRMLS_CC);
}

static void
phc_builtin_require_once (zval * arg, zval ** p_result, char *filename TSRMLS_DC)
{
  include_backend ( arg,
		    p_result,
		    filename,
		    ZEND_REQUIRE,
		    1,
		    "Failed opening required '%s' (include_path='%s')",
		    "function.require_once"
		    TSRMLS_CC);
}

// END INCLUDED FILES
int saved_refcount;
static zend_fcall_info sanitizer_decodecharreferences_fci;
static zend_fcall_info_cache sanitizer_decodecharreferences_fcic = {0,NULL,NULL,NULL};
static zend_fcall_info str_replace_fci;
static zend_fcall_info_cache str_replace_fcic = {0,NULL,NULL,NULL};
// class CoreLinkFunctions
// {
// 	static function register($parser)
// 	{
// 		$TLE5 = NS_CATEGORY;
// 		$TLE6 = 'CoreLinkFunctions';
// 		$TLE7 = 'categoryLinkHook';
// 		unset($TSa8);
// 		$TSa8 = (array) $TSa8;
// 		$TSa8[] = $TLE6;
// 		$TSa8[] = $TLE7;
// 		$parser->setlinkhook($TLE5, $TSa8);
// 		$TLE9 = True;
// 		return $TLE9;
// 	}
// 	static function defaultlinkhook($parser, $holders, $markers, title $title, $titleText, &$displayText = NULL, &$leadingColon = False)
// 	{
// 		$TLE0 = isset($displayText);
// 		if (TLE0) goto L27 else goto L28;
// 	L27:
// 		$TEF1 = $markers->findmarker($displayText);
// 		goto L29;
// 	L28:
// 		$TEF1 = $TLE0;
// 		goto L29;
// 	L29:
// 		$TLE10 = (bool) $TEF1;
// 		if (TLE10) goto L30 else goto L31;
// 	L30:
// 		$displayText = $markers->expand($displayText);
// 		$TLE11 = False;
// 		return $TLE11;
// 		goto L32;
// 	L31:
// 		goto L32;
// 	L32:
// 		$TLE12 = isset($displayText);
// 		if (TLE12) goto L33 else goto L34;
// 	L33:
// 		$TEF2 = $displayText;
// 		goto L35;
// 	L34:
// 		$TEF2 = $titleText;
// 		goto L35;
// 	L35:
// 		$TLE13 = '';
// 		$TLE14 = '';
// 		$TLE15 = '';
// 		$TLE16 = $holders->makeholder($title, $TEF2, $TLE13, $TLE14, $TLE15);
// 		return $TLE16;
// 	}
// 	static function categorylinkhook($parser, $holders, $markers, title $title, $titleText, &$sortText = NULL, &$leadingColon = False)
// 	{
// 		global $wgContLang;
// 		if (leadingColon) goto L36 else goto L37;
// 	L36:
// 		$TLE17 = True;
// 		return $TLE17;
// 		goto L38;
// 	L37:
// 		goto L38;
// 	L38:
// 		$TLE3 = isset($sortText);
// 		if (TLE3) goto L39 else goto L40;
// 	L39:
// 		$TEF4 = $markers->findmarker($sortText);
// 		goto L41;
// 	L40:
// 		$TEF4 = $TLE3;
// 		goto L41;
// 	L41:
// 		$TLE18 = (bool) $TEF4;
// 		if (TLE18) goto L42 else goto L43;
// 	L42:
// 		$sortText = $markers->expand($sortText);
// 		$TLE19 = False;
// 		return $TLE19;
// 		goto L44;
// 	L43:
// 		goto L44;
// 	L44:
// 		$TLE20 = isset($sortText);
// 		$TLE21 = !$TLE20;
// 		if (TLE21) goto L45 else goto L46;
// 	L45:
// 		$sortText = $parser->getdefaultsort();
// 		goto L47;
// 	L46:
// 		goto L47;
// 	L47:
// 		$sortText = sanitizer::decodecharreferences($sortText);
// 		$TLE22 = '
// ';
// 		$TLE23 = '';
// 		$sortText = str_replace($TLE22, $TLE23, $sortText);
// 		$sortText = $wgContLang->convertcategorykey($sortText);
// 		$TSt24 = $parser->mOutput;
// 		$TLE25 = $title->getdbkey();
// 		$TSt24->addcategory($TLE25, $sortText);
// 		$TLE26 = '';
// 		return $TLE26;
// 	}
// }
// static function register($parser)
// {
// 	$TLE5 = NS_CATEGORY;
// 	$TLE6 = 'CoreLinkFunctions';
// 	$TLE7 = 'categoryLinkHook';
// 	unset($TSa8);
// 	$TSa8 = (array) $TSa8;
// 	$TSa8[] = $TLE6;
// 	$TSa8[] = $TLE7;
// 	$parser->setlinkhook($TLE5, $TSa8);
// 	$TLE9 = True;
// 	return $TLE9;
// }
PHP_METHOD(CoreLinkFunctions, register)
{
zval* local_TLE5 = NULL;
zval* local_TLE6 = NULL;
zval* local_TLE7 = NULL;
zval* local_TLE9 = NULL;
zval* local_TSa8 = NULL;
zval* local_parser = NULL;
// Add all parameters as local variables
{
int num_args = ZEND_NUM_ARGS ();
zval* params[1];
zend_get_parameters_array(0, num_args, params);
// param 0
params[0]->refcount++;
if (local_parser != NULL)
{
	zval_ptr_dtor (&local_parser);
}
local_parser = params[0];
}
// Function body
// $TLE5 = NS_CATEGORY;
{
   // No null-terminator in length for get_constant.
   // zend_get_constant always returns a copy of the constant.
     if (local_TLE5 == NULL)
    {
      local_TLE5 = EG (uninitialized_zval_ptr);
      local_TLE5->refcount++;
    }
  zval** p_lhs = &local_TLE5;

   if (!(*p_lhs)->is_ref)
   {
        zval_ptr_dtor (p_lhs);
   get_constant ("NS_CATEGORY", 11, p_lhs TSRMLS_CC);

   }
   else
   {
         zval* constant;
    get_constant ("NS_CATEGORY", 11, p_lhs TSRMLS_CC);
    overwrite_lhs_no_copy (*p_lhs, constant);
    safe_free_zval_ptr (constant);

   }
phc_check_invariants (TSRMLS_C);
}
// $TLE6 = 'CoreLinkFunctions';
{
        if (local_TLE6 == NULL)
    {
      local_TLE6 = EG (uninitialized_zval_ptr);
      local_TLE6->refcount++;
    }
  zval** p_lhs = &local_TLE6;

   zval* value;
   if ((*p_lhs)->is_ref)
   {
     // Always overwrite the current value
     value = *p_lhs;
     zval_dtor (value);
   }
   else
   {
     ALLOC_INIT_ZVAL (value);
     zval_ptr_dtor (p_lhs);
     *p_lhs = value;
   }

   ZVAL_STRINGL(value, "CoreLinkFunctions", 17, 1);

phc_check_invariants (TSRMLS_C);
}
// $TLE7 = 'categoryLinkHook';
{
        if (local_TLE7 == NULL)
    {
      local_TLE7 = EG (uninitialized_zval_ptr);
      local_TLE7->refcount++;
    }
  zval** p_lhs = &local_TLE7;

   zval* value;
   if ((*p_lhs)->is_ref)
   {
     // Always overwrite the current value
     value = *p_lhs;
     zval_dtor (value);
   }
   else
   {
     ALLOC_INIT_ZVAL (value);
     zval_ptr_dtor (p_lhs);
     *p_lhs = value;
   }

   ZVAL_STRINGL(value, "categoryLinkHook", 16, 1);

phc_check_invariants (TSRMLS_C);
}
// unset($TSa8);
{
if (local_TSa8 != NULL)
{
zval_ptr_dtor (&local_TSa8);
local_TSa8 = NULL;
}
phc_check_invariants (TSRMLS_C);
}
// $TSa8 = (array) $TSa8;
{
      if (local_TSa8 == NULL)
    {
      local_TSa8 = EG (uninitialized_zval_ptr);
      local_TSa8->refcount++;
    }
  zval** p_lhs = &local_TSa8;

    zval* rhs;
  if (local_TSa8 == NULL)
    rhs = EG (uninitialized_zval_ptr);
  else
    rhs = local_TSa8;

  if (*p_lhs != rhs)
    {
        if ((*p_lhs)->is_ref)
      overwrite_lhs (*p_lhs, rhs);
  else
    {
      zval_ptr_dtor (p_lhs);
        if (rhs->is_ref)
    {
      // Take a copy of RHS for LHS
      *p_lhs = zvp_clone_ex (rhs);
    }
  else
    {
      // Share a copy
      rhs->refcount++;
      *p_lhs = rhs;
    }

    }

    }

    assert (IS_ARRAY >= 0 && IS_ARRAY <= 6);
  if ((*p_lhs)->type != IS_ARRAY)
  {
    sep_copy_on_write (p_lhs);
    convert_to_array (*p_lhs);
  }

phc_check_invariants (TSRMLS_C);
}
// $TSa8[] = $TLE6;
{
     if (local_TSa8 == NULL)
    {
      local_TSa8 = EG (uninitialized_zval_ptr);
      local_TSa8->refcount++;
    }
  zval** p_array = &local_TSa8;

   // Push EG(uninit) and get a pointer to the symtable entry
   zval** p_lhs = push_and_index_ht (p_array TSRMLS_CC);
   if (p_lhs != NULL)
   {
        zval* rhs;
  if (local_TLE6 == NULL)
    rhs = EG (uninitialized_zval_ptr);
  else
    rhs = local_TLE6;

      if (*p_lhs != rhs)
	 write_var (p_lhs, rhs);
   }
   // I think if this is NULL, then the LHS is a bool or similar, and you cant
   // push onto it.
phc_check_invariants (TSRMLS_C);
}
// $TSa8[] = $TLE7;
{
     if (local_TSa8 == NULL)
    {
      local_TSa8 = EG (uninitialized_zval_ptr);
      local_TSa8->refcount++;
    }
  zval** p_array = &local_TSa8;

   // Push EG(uninit) and get a pointer to the symtable entry
   zval** p_lhs = push_and_index_ht (p_array TSRMLS_CC);
   if (p_lhs != NULL)
   {
        zval* rhs;
  if (local_TLE7 == NULL)
    rhs = EG (uninitialized_zval_ptr);
  else
    rhs = local_TLE7;

      if (*p_lhs != rhs)
	 write_var (p_lhs, rhs);
   }
   // I think if this is NULL, then the LHS is a bool or similar, and you cant
   // push onto it.
phc_check_invariants (TSRMLS_C);
}
// $parser->setlinkhook($TLE5, $TSa8);
{
     if (local_parser == NULL)
    {
      local_parser = EG (uninitialized_zval_ptr);
      local_parser->refcount++;
    }
  zval** p_obj = &local_parser;

   zend_fcall_info fci_object;
   zend_fcall_info_cache fcic_object = {0, NULL, NULL, NULL};
   initialize_method_call (&fci_object, &fcic_object, p_obj, "setlinkhook", "/home/mdupont/2009/02/introspector/rdfintrospector/mediawiki/trunk/phase3/includes/parser/CoreLinkFunctions.php", 9 TSRMLS_CC);
      zend_function* signature = fcic_object.function_handler;
   zend_arg_info* arg_info = signature->common.arg_info; // optional

   int by_ref[2];
   int abr_index = 0;
      // TODO: find names to replace index
   if (arg_info)
   {
      by_ref[abr_index] = arg_info->pass_by_reference;
      arg_info++;
   }
   else
      by_ref[abr_index] = signature->common.pass_rest_by_reference;

   abr_index++;
   // TODO: find names to replace index
   if (arg_info)
   {
      by_ref[abr_index] = arg_info->pass_by_reference;
      arg_info++;
   }
   else
      by_ref[abr_index] = signature->common.pass_rest_by_reference;

   abr_index++;


   // Setup array of arguments
   // TODO: i think arrays of size 0 is an error
   int destruct [2];
   zval* args [2];
   zval** args_ind [2];

   int af_index = 0;
      destruct[af_index] = 0;
   if (by_ref[af_index])
   {
        if (local_TLE5 == NULL)
    {
      local_TLE5 = EG (uninitialized_zval_ptr);
      local_TLE5->refcount++;
    }
  zval** p_arg = &local_TLE5;

      args_ind[af_index] = fetch_var_arg_by_ref (p_arg);
      assert (!in_copy_on_write (*args_ind[af_index]));
      args[af_index] = *args_ind[af_index];
   }
   else
   {
        zval* arg;
  if (local_TLE5 == NULL)
    arg = EG (uninitialized_zval_ptr);
  else
    arg = local_TLE5;

      args[af_index] = fetch_var_arg (arg, &destruct[af_index]);
      args_ind[af_index] = &args[af_index];
   }
   af_index++;
   destruct[af_index] = 0;
   if (by_ref[af_index])
   {
        if (local_TSa8 == NULL)
    {
      local_TSa8 = EG (uninitialized_zval_ptr);
      local_TSa8->refcount++;
    }
  zval** p_arg = &local_TSa8;

      args_ind[af_index] = fetch_var_arg_by_ref (p_arg);
      assert (!in_copy_on_write (*args_ind[af_index]));
      args[af_index] = *args_ind[af_index];
   }
   else
   {
        zval* arg;
  if (local_TSa8 == NULL)
    arg = EG (uninitialized_zval_ptr);
  else
    arg = local_TSa8;

      args[af_index] = fetch_var_arg (arg, &destruct[af_index]);
      args_ind[af_index] = &args[af_index];
   }
   af_index++;


   phc_setup_error (1, "/home/mdupont/2009/02/introspector/rdfintrospector/mediawiki/trunk/phase3/includes/parser/CoreLinkFunctions.php", 9, NULL TSRMLS_CC);

   // save existing parameters, in case of recursion
   int param_count_save = fci_object.param_count;
   zval*** params_save = fci_object.params;
   zval** retval_save = fci_object.retval_ptr_ptr;

   zval* rhs = NULL;

   // set up params
   fci_object.params = args_ind;
   fci_object.param_count = 2;
   fci_object.retval_ptr_ptr = &rhs;

   // call the function
   int success = zend_call_function (&fci_object, &fcic_object TSRMLS_CC);
   assert(success == SUCCESS);

   // restore params
   fci_object.params = params_save;
   fci_object.param_count = param_count_save;
   fci_object.retval_ptr_ptr = retval_save;

   // unset the errors
   phc_setup_error (0, NULL, 0, NULL TSRMLS_CC);

   int i;
   for (i = 0; i < 2; i++)
   {
      if (destruct[i])
      {
	 assert (destruct[i]);
	 zval_ptr_dtor (args_ind[i]);
      }
   }


   // When the Zend engine returns by reference, it allocates a zval into
   // retval_ptr_ptr. To return by reference, the callee writes into the
   // retval_ptr_ptr, freeing the allocated value as it does.  (Note, it may
   // not actually return anything). So the zval returned - whether we return
   // it, or it is the allocated zval - has a refcount of 1.
 
   // The caller is responsible for cleaning that up (note, this is unaffected
   // by whether it is added to some COW set).

   // For reasons unknown, the Zend API resets the refcount and is_ref fields
   // of the return value after the function returns (unless the callee is
   // interpreted). If the function is supposed to return by reference, this
   // loses the refcount. This only happens when non-interpreted code is
   // called. We work around it, when compiled code is called, by saving the
   // refcount into SAVED_REFCOUNT, in the return statement. The downside is
   // that we may create an error if our code is called by a callback, and
   // returns by reference, and the callback returns by reference. At least
   // this is an obscure case.
   if(signature->common.return_reference && signature->type != ZEND_USER_FUNCTION)
   {
      assert (rhs != EG(uninitialized_zval_ptr));
      rhs->is_ref = 1;
      if (saved_refcount != 0)
      {
	 rhs->refcount = saved_refcount;
      }
      rhs->refcount++;
   }
   saved_refcount = 0; // for 'obscure cases'

   

   zval_ptr_dtor (&rhs);
   if(signature->common.return_reference && signature->type != ZEND_USER_FUNCTION)
      zval_ptr_dtor (&rhs);

phc_check_invariants (TSRMLS_C);
}
// $TLE9 = True;
{
        if (local_TLE9 == NULL)
    {
      local_TLE9 = EG (uninitialized_zval_ptr);
      local_TLE9->refcount++;
    }
  zval** p_lhs = &local_TLE9;

   zval* value;
   if ((*p_lhs)->is_ref)
   {
     // Always overwrite the current value
     value = *p_lhs;
     zval_dtor (value);
   }
   else
   {
     ALLOC_INIT_ZVAL (value);
     zval_ptr_dtor (p_lhs);
     *p_lhs = value;
   }

   ZVAL_BOOL (value, 1);

phc_check_invariants (TSRMLS_C);
}
// return $TLE9;
{
     zval* rhs;
  if (local_TLE9 == NULL)
    rhs = EG (uninitialized_zval_ptr);
  else
    rhs = local_TLE9;

   // Run-time return by reference has different semantics to compile-time.
   // If the function has CTRBR and RTRBR, the the assignment will be
   // reference. If one or the other is return-by-copy, the result will be
   // by copy. Its a question of whether its separated at return-time (which
   // we do here) or at the call-site.
   return_value->value = rhs->value;
   return_value->type = rhs->type;
   zval_copy_ctor (return_value);
   goto end_of_function;
phc_check_invariants (TSRMLS_C);
}
// Method exit
end_of_function:__attribute__((unused));
if (local_TLE5 != NULL)
{
zval_ptr_dtor (&local_TLE5);
}
if (local_TLE6 != NULL)
{
zval_ptr_dtor (&local_TLE6);
}
if (local_TLE7 != NULL)
{
zval_ptr_dtor (&local_TLE7);
}
if (local_TLE9 != NULL)
{
zval_ptr_dtor (&local_TLE9);
}
if (local_TSa8 != NULL)
{
zval_ptr_dtor (&local_TSa8);
}
if (local_parser != NULL)
{
zval_ptr_dtor (&local_parser);
}
}
// static function defaultlinkhook($parser, $holders, $markers, title $title, $titleText, &$displayText = NULL, &$leadingColon = False)
// {
// 	$TLE0 = isset($displayText);
// 	if (TLE0) goto L27 else goto L28;
// L27:
// 	$TEF1 = $markers->findmarker($displayText);
// 	goto L29;
// L28:
// 	$TEF1 = $TLE0;
// 	goto L29;
// L29:
// 	$TLE10 = (bool) $TEF1;
// 	if (TLE10) goto L30 else goto L31;
// L30:
// 	$displayText = $markers->expand($displayText);
// 	$TLE11 = False;
// 	return $TLE11;
// 	goto L32;
// L31:
// 	goto L32;
// L32:
// 	$TLE12 = isset($displayText);
// 	if (TLE12) goto L33 else goto L34;
// L33:
// 	$TEF2 = $displayText;
// 	goto L35;
// L34:
// 	$TEF2 = $titleText;
// 	goto L35;
// L35:
// 	$TLE13 = '';
// 	$TLE14 = '';
// 	$TLE15 = '';
// 	$TLE16 = $holders->makeholder($title, $TEF2, $TLE13, $TLE14, $TLE15);
// 	return $TLE16;
// }
PHP_METHOD(CoreLinkFunctions, defaultlinkhook)
{
zval* local_TEF1 = NULL;
zval* local_TEF2 = NULL;
zval* local_TLE0 = NULL;
zval* local_TLE10 = NULL;
zval* local_TLE11 = NULL;
zval* local_TLE12 = NULL;
zval* local_TLE13 = NULL;
zval* local_TLE14 = NULL;
zval* local_TLE15 = NULL;
zval* local_TLE16 = NULL;
zval* local_displayText = NULL;
zval* local_holders = NULL;
zval* local_leadingColon = NULL;
zval* local_markers = NULL;
zval* local_parser = NULL;
zval* local_title = NULL;
zval* local_titleText = NULL;
// Add all parameters as local variables
{
int num_args = ZEND_NUM_ARGS ();
zval* params[7];
zend_get_parameters_array(0, num_args, params);
// param 0
params[0]->refcount++;
if (local_parser != NULL)
{
	zval_ptr_dtor (&local_parser);
}
local_parser = params[0];
// param 1
params[1]->refcount++;
if (local_holders != NULL)
{
	zval_ptr_dtor (&local_holders);
}
local_holders = params[1];
// param 2
params[2]->refcount++;
if (local_markers != NULL)
{
	zval_ptr_dtor (&local_markers);
}
local_markers = params[2];
// param 3
params[3]->refcount++;
if (local_title != NULL)
{
	zval_ptr_dtor (&local_title);
}
local_title = params[3];
// param 4
params[4]->refcount++;
if (local_titleText != NULL)
{
	zval_ptr_dtor (&local_titleText);
}
local_titleText = params[4];
// param 5
if (num_args <= 5)
{
zval* default_value;
{
zval* local___static_value__ = NULL;
// $__static_value__ = NULL;
{
        if (local___static_value__ == NULL)
    {
      local___static_value__ = EG (uninitialized_zval_ptr);
      local___static_value__->refcount++;
    }
  zval** p_lhs = &local___static_value__;

   zval* value;
   if ((*p_lhs)->is_ref)
   {
     // Always overwrite the current value
     value = *p_lhs;
     zval_dtor (value);
   }
   else
   {
     ALLOC_INIT_ZVAL (value);
     zval_ptr_dtor (p_lhs);
     *p_lhs = value;
   }

   ZVAL_NULL (value);

phc_check_invariants (TSRMLS_C);
}
default_value = local___static_value__;
assert(!default_value->is_ref);
default_value->refcount++;
if (local___static_value__ != NULL)
{
zval_ptr_dtor (&local___static_value__);
}
}
default_value->refcount--;
	params[5] = default_value;
}
params[5]->refcount++;
if (local_displayText != NULL)
{
	zval_ptr_dtor (&local_displayText);
}
local_displayText = params[5];
// param 6
if (num_args <= 6)
{
zval* default_value;
{
zval* local___static_value__ = NULL;
// $__static_value__ = False;
{
        if (local___static_value__ == NULL)
    {
      local___static_value__ = EG (uninitialized_zval_ptr);
      local___static_value__->refcount++;
    }
  zval** p_lhs = &local___static_value__;

   zval* value;
   if ((*p_lhs)->is_ref)
   {
     // Always overwrite the current value
     value = *p_lhs;
     zval_dtor (value);
   }
   else
   {
     ALLOC_INIT_ZVAL (value);
     zval_ptr_dtor (p_lhs);
     *p_lhs = value;
   }

   ZVAL_BOOL (value, 0);

phc_check_invariants (TSRMLS_C);
}
default_value = local___static_value__;
assert(!default_value->is_ref);
default_value->refcount++;
if (local___static_value__ != NULL)
{
zval_ptr_dtor (&local___static_value__);
}
}
default_value->refcount--;
	params[6] = default_value;
}
params[6]->refcount++;
if (local_leadingColon != NULL)
{
	zval_ptr_dtor (&local_leadingColon);
}
local_leadingColon = params[6];
}
// Function body
// $TLE0 = isset($displayText);
{
if (local_TLE0 == NULL)
{
local_TLE0 = EG (uninitialized_zval_ptr);
local_TLE0->refcount++;
}
zval** p_lhs = &local_TLE0;
zval* value;
if ((*p_lhs)->is_ref)
{
  // Always overwrite the current value
  value = *p_lhs;
  zval_dtor (value);
}
else
{
	ALLOC_INIT_ZVAL (value);
	zval_ptr_dtor (p_lhs);
	*p_lhs = value;
}
ZVAL_BOOL(value, local_displayText != NULL && !ZVAL_IS_NULL(local_displayText));
phc_check_invariants (TSRMLS_C);
}
// if (TLE0) goto L27 else goto L28;
{
     zval* p_cond;
  if (local_TLE0 == NULL)
    p_cond = EG (uninitialized_zval_ptr);
  else
    p_cond = local_TLE0;

   zend_bool bcond = zend_is_true (p_cond);
   if (bcond)
      goto L27;
   else
      goto L28;
phc_check_invariants (TSRMLS_C);
}
// L27:
L27:;
// $TEF1 = $markers->findmarker($displayText);
{
     if (local_markers == NULL)
    {
      local_markers = EG (uninitialized_zval_ptr);
      local_markers->refcount++;
    }
  zval** p_obj = &local_markers;

   zend_fcall_info fci_object;
   zend_fcall_info_cache fcic_object = {0, NULL, NULL, NULL};
   initialize_method_call (&fci_object, &fcic_object, p_obj, "findmarker", "/home/mdupont/2009/02/introspector/rdfintrospector/mediawiki/trunk/phase3/includes/parser/CoreLinkFunctions.php", 15 TSRMLS_CC);
      zend_function* signature = fcic_object.function_handler;
   zend_arg_info* arg_info = signature->common.arg_info; // optional

   int by_ref[1];
   int abr_index = 0;
      // TODO: find names to replace index
   if (arg_info)
   {
      by_ref[abr_index] = arg_info->pass_by_reference;
      arg_info++;
   }
   else
      by_ref[abr_index] = signature->common.pass_rest_by_reference;

   abr_index++;


   // Setup array of arguments
   // TODO: i think arrays of size 0 is an error
   int destruct [1];
   zval* args [1];
   zval** args_ind [1];

   int af_index = 0;
      destruct[af_index] = 0;
   if (by_ref[af_index])
   {
        if (local_displayText == NULL)
    {
      local_displayText = EG (uninitialized_zval_ptr);
      local_displayText->refcount++;
    }
  zval** p_arg = &local_displayText;

      args_ind[af_index] = fetch_var_arg_by_ref (p_arg);
      assert (!in_copy_on_write (*args_ind[af_index]));
      args[af_index] = *args_ind[af_index];
   }
   else
   {
        zval* arg;
  if (local_displayText == NULL)
    arg = EG (uninitialized_zval_ptr);
  else
    arg = local_displayText;

      args[af_index] = fetch_var_arg (arg, &destruct[af_index]);
      args_ind[af_index] = &args[af_index];
   }
   af_index++;


   phc_setup_error (1, "/home/mdupont/2009/02/introspector/rdfintrospector/mediawiki/trunk/phase3/includes/parser/CoreLinkFunctions.php", 15, NULL TSRMLS_CC);

   // save existing parameters, in case of recursion
   int param_count_save = fci_object.param_count;
   zval*** params_save = fci_object.params;
   zval** retval_save = fci_object.retval_ptr_ptr;

   zval* rhs = NULL;

   // set up params
   fci_object.params = args_ind;
   fci_object.param_count = 1;
   fci_object.retval_ptr_ptr = &rhs;

   // call the function
   int success = zend_call_function (&fci_object, &fcic_object TSRMLS_CC);
   assert(success == SUCCESS);

   // restore params
   fci_object.params = params_save;
   fci_object.param_count = param_count_save;
   fci_object.retval_ptr_ptr = retval_save;

   // unset the errors
   phc_setup_error (0, NULL, 0, NULL TSRMLS_CC);

   int i;
   for (i = 0; i < 1; i++)
   {
      if (destruct[i])
      {
	 assert (destruct[i]);
	 zval_ptr_dtor (args_ind[i]);
      }
   }


   // When the Zend engine returns by reference, it allocates a zval into
   // retval_ptr_ptr. To return by reference, the callee writes into the
   // retval_ptr_ptr, freeing the allocated value as it does.  (Note, it may
   // not actually return anything). So the zval returned - whether we return
   // it, or it is the allocated zval - has a refcount of 1.
 
   // The caller is responsible for cleaning that up (note, this is unaffected
   // by whether it is added to some COW set).

   // For reasons unknown, the Zend API resets the refcount and is_ref fields
   // of the return value after the function returns (unless the callee is
   // interpreted). If the function is supposed to return by reference, this
   // loses the refcount. This only happens when non-interpreted code is
   // called. We work around it, when compiled code is called, by saving the
   // refcount into SAVED_REFCOUNT, in the return statement. The downside is
   // that we may create an error if our code is called by a callback, and
   // returns by reference, and the callback returns by reference. At least
   // this is an obscure case.
   if(signature->common.return_reference && signature->type != ZEND_USER_FUNCTION)
   {
      assert (rhs != EG(uninitialized_zval_ptr));
      rhs->is_ref = 1;
      if (saved_refcount != 0)
      {
	 rhs->refcount = saved_refcount;
      }
      rhs->refcount++;
   }
   saved_refcount = 0; // for 'obscure cases'

        if (local_TEF1 == NULL)
    {
      local_TEF1 = EG (uninitialized_zval_ptr);
      local_TEF1->refcount++;
    }
  zval** p_lhs = &local_TEF1;

   write_var (p_lhs, rhs);


   zval_ptr_dtor (&rhs);
   if(signature->common.return_reference && signature->type != ZEND_USER_FUNCTION)
      zval_ptr_dtor (&rhs);

phc_check_invariants (TSRMLS_C);
}
// goto L29;
{
goto L29;
phc_check_invariants (TSRMLS_C);
}
// L28:
L28:;
// $TEF1 = $TLE0;
{
    if (local_TEF1 == NULL)
    {
      local_TEF1 = EG (uninitialized_zval_ptr);
      local_TEF1->refcount++;
    }
  zval** p_lhs = &local_TEF1;

    zval* rhs;
  if (local_TLE0 == NULL)
    rhs = EG (uninitialized_zval_ptr);
  else
    rhs = local_TLE0;

  if (*p_lhs != rhs)
    {
        if ((*p_lhs)->is_ref)
      overwrite_lhs (*p_lhs, rhs);
  else
    {
      zval_ptr_dtor (p_lhs);
        if (rhs->is_ref)
    {
      // Take a copy of RHS for LHS
      *p_lhs = zvp_clone_ex (rhs);
    }
  else
    {
      // Share a copy
      rhs->refcount++;
      *p_lhs = rhs;
    }

    }

    }
phc_check_invariants (TSRMLS_C);
}
// goto L29;
{
goto L29;
phc_check_invariants (TSRMLS_C);
}
// L29:
L29:;
// $TLE10 = (bool) $TEF1;
{
      if (local_TLE10 == NULL)
    {
      local_TLE10 = EG (uninitialized_zval_ptr);
      local_TLE10->refcount++;
    }
  zval** p_lhs = &local_TLE10;

    zval* rhs;
  if (local_TEF1 == NULL)
    rhs = EG (uninitialized_zval_ptr);
  else
    rhs = local_TEF1;

  if (*p_lhs != rhs)
    {
        if ((*p_lhs)->is_ref)
      overwrite_lhs (*p_lhs, rhs);
  else
    {
      zval_ptr_dtor (p_lhs);
        if (rhs->is_ref)
    {
      // Take a copy of RHS for LHS
      *p_lhs = zvp_clone_ex (rhs);
    }
  else
    {
      // Share a copy
      rhs->refcount++;
      *p_lhs = rhs;
    }

    }

    }

    assert (IS_BOOL >= 0 && IS_BOOL <= 6);
  if ((*p_lhs)->type != IS_BOOL)
  {
    sep_copy_on_write (p_lhs);
    convert_to_boolean (*p_lhs);
  }

phc_check_invariants (TSRMLS_C);
}
// if (TLE10) goto L30 else goto L31;
{
     zval* p_cond;
  if (local_TLE10 == NULL)
    p_cond = EG (uninitialized_zval_ptr);
  else
    p_cond = local_TLE10;

   zend_bool bcond = zend_is_true (p_cond);
   if (bcond)
      goto L30;
   else
      goto L31;
phc_check_invariants (TSRMLS_C);
}
// L30:
L30:;
// $displayText = $markers->expand($displayText);
{
     if (local_markers == NULL)
    {
      local_markers = EG (uninitialized_zval_ptr);
      local_markers->refcount++;
    }
  zval** p_obj = &local_markers;

   zend_fcall_info fci_object;
   zend_fcall_info_cache fcic_object = {0, NULL, NULL, NULL};
   initialize_method_call (&fci_object, &fcic_object, p_obj, "expand", "/home/mdupont/2009/02/introspector/rdfintrospector/mediawiki/trunk/phase3/includes/parser/CoreLinkFunctions.php", 19 TSRMLS_CC);
      zend_function* signature = fcic_object.function_handler;
   zend_arg_info* arg_info = signature->common.arg_info; // optional

   int by_ref[1];
   int abr_index = 0;
      // TODO: find names to replace index
   if (arg_info)
   {
      by_ref[abr_index] = arg_info->pass_by_reference;
      arg_info++;
   }
   else
      by_ref[abr_index] = signature->common.pass_rest_by_reference;

   abr_index++;


   // Setup array of arguments
   // TODO: i think arrays of size 0 is an error
   int destruct [1];
   zval* args [1];
   zval** args_ind [1];

   int af_index = 0;
      destruct[af_index] = 0;
   if (by_ref[af_index])
   {
        if (local_displayText == NULL)
    {
      local_displayText = EG (uninitialized_zval_ptr);
      local_displayText->refcount++;
    }
  zval** p_arg = &local_displayText;

      args_ind[af_index] = fetch_var_arg_by_ref (p_arg);
      assert (!in_copy_on_write (*args_ind[af_index]));
      args[af_index] = *args_ind[af_index];
   }
   else
   {
        zval* arg;
  if (local_displayText == NULL)
    arg = EG (uninitialized_zval_ptr);
  else
    arg = local_displayText;

      args[af_index] = fetch_var_arg (arg, &destruct[af_index]);
      args_ind[af_index] = &args[af_index];
   }
   af_index++;


   phc_setup_error (1, "/home/mdupont/2009/02/introspector/rdfintrospector/mediawiki/trunk/phase3/includes/parser/CoreLinkFunctions.php", 19, NULL TSRMLS_CC);

   // save existing parameters, in case of recursion
   int param_count_save = fci_object.param_count;
   zval*** params_save = fci_object.params;
   zval** retval_save = fci_object.retval_ptr_ptr;

   zval* rhs = NULL;

   // set up params
   fci_object.params = args_ind;
   fci_object.param_count = 1;
   fci_object.retval_ptr_ptr = &rhs;

   // call the function
   int success = zend_call_function (&fci_object, &fcic_object TSRMLS_CC);
   assert(success == SUCCESS);

   // restore params
   fci_object.params = params_save;
   fci_object.param_count = param_count_save;
   fci_object.retval_ptr_ptr = retval_save;

   // unset the errors
   phc_setup_error (0, NULL, 0, NULL TSRMLS_CC);

   int i;
   for (i = 0; i < 1; i++)
   {
      if (destruct[i])
      {
	 assert (destruct[i]);
	 zval_ptr_dtor (args_ind[i]);
      }
   }


   // When the Zend engine returns by reference, it allocates a zval into
   // retval_ptr_ptr. To return by reference, the callee writes into the
   // retval_ptr_ptr, freeing the allocated value as it does.  (Note, it may
   // not actually return anything). So the zval returned - whether we return
   // it, or it is the allocated zval - has a refcount of 1.
 
   // The caller is responsible for cleaning that up (note, this is unaffected
   // by whether it is added to some COW set).

   // For reasons unknown, the Zend API resets the refcount and is_ref fields
   // of the return value after the function returns (unless the callee is
   // interpreted). If the function is supposed to return by reference, this
   // loses the refcount. This only happens when non-interpreted code is
   // called. We work around it, when compiled code is called, by saving the
   // refcount into SAVED_REFCOUNT, in the return statement. The downside is
   // that we may create an error if our code is called by a callback, and
   // returns by reference, and the callback returns by reference. At least
   // this is an obscure case.
   if(signature->common.return_reference && signature->type != ZEND_USER_FUNCTION)
   {
      assert (rhs != EG(uninitialized_zval_ptr));
      rhs->is_ref = 1;
      if (saved_refcount != 0)
      {
	 rhs->refcount = saved_refcount;
      }
      rhs->refcount++;
   }
   saved_refcount = 0; // for 'obscure cases'

        if (local_displayText == NULL)
    {
      local_displayText = EG (uninitialized_zval_ptr);
      local_displayText->refcount++;
    }
  zval** p_lhs = &local_displayText;

   write_var (p_lhs, rhs);


   zval_ptr_dtor (&rhs);
   if(signature->common.return_reference && signature->type != ZEND_USER_FUNCTION)
      zval_ptr_dtor (&rhs);

phc_check_invariants (TSRMLS_C);
}
// $TLE11 = False;
{
        if (local_TLE11 == NULL)
    {
      local_TLE11 = EG (uninitialized_zval_ptr);
      local_TLE11->refcount++;
    }
  zval** p_lhs = &local_TLE11;

   zval* value;
   if ((*p_lhs)->is_ref)
   {
     // Always overwrite the current value
     value = *p_lhs;
     zval_dtor (value);
   }
   else
   {
     ALLOC_INIT_ZVAL (value);
     zval_ptr_dtor (p_lhs);
     *p_lhs = value;
   }

   ZVAL_BOOL (value, 0);

phc_check_invariants (TSRMLS_C);
}
// return $TLE11;
{
     zval* rhs;
  if (local_TLE11 == NULL)
    rhs = EG (uninitialized_zval_ptr);
  else
    rhs = local_TLE11;

   // Run-time return by reference has different semantics to compile-time.
   // If the function has CTRBR and RTRBR, the the assignment will be
   // reference. If one or the other is return-by-copy, the result will be
   // by copy. Its a question of whether its separated at return-time (which
   // we do here) or at the call-site.
   return_value->value = rhs->value;
   return_value->type = rhs->type;
   zval_copy_ctor (return_value);
   goto end_of_function;
phc_check_invariants (TSRMLS_C);
}
// goto L32;
{
goto L32;
phc_check_invariants (TSRMLS_C);
}
// L31:
L31:;
// goto L32;
{
goto L32;
phc_check_invariants (TSRMLS_C);
}
// L32:
L32:;
// $TLE12 = isset($displayText);
{
if (local_TLE12 == NULL)
{
local_TLE12 = EG (uninitialized_zval_ptr);
local_TLE12->refcount++;
}
zval** p_lhs = &local_TLE12;
zval* value;
if ((*p_lhs)->is_ref)
{
  // Always overwrite the current value
  value = *p_lhs;
  zval_dtor (value);
}
else
{
	ALLOC_INIT_ZVAL (value);
	zval_ptr_dtor (p_lhs);
	*p_lhs = value;
}
ZVAL_BOOL(value, local_displayText != NULL && !ZVAL_IS_NULL(local_displayText));
phc_check_invariants (TSRMLS_C);
}
// if (TLE12) goto L33 else goto L34;
{
     zval* p_cond;
  if (local_TLE12 == NULL)
    p_cond = EG (uninitialized_zval_ptr);
  else
    p_cond = local_TLE12;

   zend_bool bcond = zend_is_true (p_cond);
   if (bcond)
      goto L33;
   else
      goto L34;
phc_check_invariants (TSRMLS_C);
}
// L33:
L33:;
// $TEF2 = $displayText;
{
    if (local_TEF2 == NULL)
    {
      local_TEF2 = EG (uninitialized_zval_ptr);
      local_TEF2->refcount++;
    }
  zval** p_lhs = &local_TEF2;

    zval* rhs;
  if (local_displayText == NULL)
    rhs = EG (uninitialized_zval_ptr);
  else
    rhs = local_displayText;

  if (*p_lhs != rhs)
    {
        if ((*p_lhs)->is_ref)
      overwrite_lhs (*p_lhs, rhs);
  else
    {
      zval_ptr_dtor (p_lhs);
        if (rhs->is_ref)
    {
      // Take a copy of RHS for LHS
      *p_lhs = zvp_clone_ex (rhs);
    }
  else
    {
      // Share a copy
      rhs->refcount++;
      *p_lhs = rhs;
    }

    }

    }
phc_check_invariants (TSRMLS_C);
}
// goto L35;
{
goto L35;
phc_check_invariants (TSRMLS_C);
}
// L34:
L34:;
// $TEF2 = $titleText;
{
    if (local_TEF2 == NULL)
    {
      local_TEF2 = EG (uninitialized_zval_ptr);
      local_TEF2->refcount++;
    }
  zval** p_lhs = &local_TEF2;

    zval* rhs;
  if (local_titleText == NULL)
    rhs = EG (uninitialized_zval_ptr);
  else
    rhs = local_titleText;

  if (*p_lhs != rhs)
    {
        if ((*p_lhs)->is_ref)
      overwrite_lhs (*p_lhs, rhs);
  else
    {
      zval_ptr_dtor (p_lhs);
        if (rhs->is_ref)
    {
      // Take a copy of RHS for LHS
      *p_lhs = zvp_clone_ex (rhs);
    }
  else
    {
      // Share a copy
      rhs->refcount++;
      *p_lhs = rhs;
    }

    }

    }
phc_check_invariants (TSRMLS_C);
}
// goto L35;
{
goto L35;
phc_check_invariants (TSRMLS_C);
}
// L35:
L35:;
// $TLE13 = '';
{
        if (local_TLE13 == NULL)
    {
      local_TLE13 = EG (uninitialized_zval_ptr);
      local_TLE13->refcount++;
    }
  zval** p_lhs = &local_TLE13;

   zval* value;
   if ((*p_lhs)->is_ref)
   {
     // Always overwrite the current value
     value = *p_lhs;
     zval_dtor (value);
   }
   else
   {
     ALLOC_INIT_ZVAL (value);
     zval_ptr_dtor (p_lhs);
     *p_lhs = value;
   }

   ZVAL_STRINGL(value, "", 0, 1);

phc_check_invariants (TSRMLS_C);
}
// $TLE14 = '';
{
        if (local_TLE14 == NULL)
    {
      local_TLE14 = EG (uninitialized_zval_ptr);
      local_TLE14->refcount++;
    }
  zval** p_lhs = &local_TLE14;

   zval* value;
   if ((*p_lhs)->is_ref)
   {
     // Always overwrite the current value
     value = *p_lhs;
     zval_dtor (value);
   }
   else
   {
     ALLOC_INIT_ZVAL (value);
     zval_ptr_dtor (p_lhs);
     *p_lhs = value;
   }

   ZVAL_STRINGL(value, "", 0, 1);

phc_check_invariants (TSRMLS_C);
}
// $TLE15 = '';
{
        if (local_TLE15 == NULL)
    {
      local_TLE15 = EG (uninitialized_zval_ptr);
      local_TLE15->refcount++;
    }
  zval** p_lhs = &local_TLE15;

   zval* value;
   if ((*p_lhs)->is_ref)
   {
     // Always overwrite the current value
     value = *p_lhs;
     zval_dtor (value);
   }
   else
   {
     ALLOC_INIT_ZVAL (value);
     zval_ptr_dtor (p_lhs);
     *p_lhs = value;
   }

   ZVAL_STRINGL(value, "", 0, 1);

phc_check_invariants (TSRMLS_C);
}
// $TLE16 = $holders->makeholder($title, $TEF2, $TLE13, $TLE14, $TLE15);
{
     if (local_holders == NULL)
    {
      local_holders = EG (uninitialized_zval_ptr);
      local_holders->refcount++;
    }
  zval** p_obj = &local_holders;

   zend_fcall_info fci_object;
   zend_fcall_info_cache fcic_object = {0, NULL, NULL, NULL};
   initialize_method_call (&fci_object, &fcic_object, p_obj, "makeholder", "/home/mdupont/2009/02/introspector/rdfintrospector/mediawiki/trunk/phase3/includes/parser/CoreLinkFunctions.php", 23 TSRMLS_CC);
      zend_function* signature = fcic_object.function_handler;
   zend_arg_info* arg_info = signature->common.arg_info; // optional

   int by_ref[5];
   int abr_index = 0;
      // TODO: find names to replace index
   if (arg_info)
   {
      by_ref[abr_index] = arg_info->pass_by_reference;
      arg_info++;
   }
   else
      by_ref[abr_index] = signature->common.pass_rest_by_reference;

   abr_index++;
   // TODO: find names to replace index
   if (arg_info)
   {
      by_ref[abr_index] = arg_info->pass_by_reference;
      arg_info++;
   }
   else
      by_ref[abr_index] = signature->common.pass_rest_by_reference;

   abr_index++;
   // TODO: find names to replace index
   if (arg_info)
   {
      by_ref[abr_index] = arg_info->pass_by_reference;
      arg_info++;
   }
   else
      by_ref[abr_index] = signature->common.pass_rest_by_reference;

   abr_index++;
   // TODO: find names to replace index
   if (arg_info)
   {
      by_ref[abr_index] = arg_info->pass_by_reference;
      arg_info++;
   }
   else
      by_ref[abr_index] = signature->common.pass_rest_by_reference;

   abr_index++;
   // TODO: find names to replace index
   if (arg_info)
   {
      by_ref[abr_index] = arg_info->pass_by_reference;
      arg_info++;
   }
   else
      by_ref[abr_index] = signature->common.pass_rest_by_reference;

   abr_index++;


   // Setup array of arguments
   // TODO: i think arrays of size 0 is an error
   int destruct [5];
   zval* args [5];
   zval** args_ind [5];

   int af_index = 0;
      destruct[af_index] = 0;
   if (by_ref[af_index])
   {
        if (local_title == NULL)
    {
      local_title = EG (uninitialized_zval_ptr);
      local_title->refcount++;
    }
  zval** p_arg = &local_title;

      args_ind[af_index] = fetch_var_arg_by_ref (p_arg);
      assert (!in_copy_on_write (*args_ind[af_index]));
      args[af_index] = *args_ind[af_index];
   }
   else
   {
        zval* arg;
  if (local_title == NULL)
    arg = EG (uninitialized_zval_ptr);
  else
    arg = local_title;

      args[af_index] = fetch_var_arg (arg, &destruct[af_index]);
      args_ind[af_index] = &args[af_index];
   }
   af_index++;
   destruct[af_index] = 0;
   if (by_ref[af_index])
   {
        if (local_TEF2 == NULL)
    {
      local_TEF2 = EG (uninitialized_zval_ptr);
      local_TEF2->refcount++;
    }
  zval** p_arg = &local_TEF2;

      args_ind[af_index] = fetch_var_arg_by_ref (p_arg);
      assert (!in_copy_on_write (*args_ind[af_index]));
      args[af_index] = *args_ind[af_index];
   }
   else
   {
        zval* arg;
  if (local_TEF2 == NULL)
    arg = EG (uninitialized_zval_ptr);
  else
    arg = local_TEF2;

      args[af_index] = fetch_var_arg (arg, &destruct[af_index]);
      args_ind[af_index] = &args[af_index];
   }
   af_index++;
   destruct[af_index] = 0;
   if (by_ref[af_index])
   {
        if (local_TLE13 == NULL)
    {
      local_TLE13 = EG (uninitialized_zval_ptr);
      local_TLE13->refcount++;
    }
  zval** p_arg = &local_TLE13;

      args_ind[af_index] = fetch_var_arg_by_ref (p_arg);
      assert (!in_copy_on_write (*args_ind[af_index]));
      args[af_index] = *args_ind[af_index];
   }
   else
   {
        zval* arg;
  if (local_TLE13 == NULL)
    arg = EG (uninitialized_zval_ptr);
  else
    arg = local_TLE13;

      args[af_index] = fetch_var_arg (arg, &destruct[af_index]);
      args_ind[af_index] = &args[af_index];
   }
   af_index++;
   destruct[af_index] = 0;
   if (by_ref[af_index])
   {
        if (local_TLE14 == NULL)
    {
      local_TLE14 = EG (uninitialized_zval_ptr);
      local_TLE14->refcount++;
    }
  zval** p_arg = &local_TLE14;

      args_ind[af_index] = fetch_var_arg_by_ref (p_arg);
      assert (!in_copy_on_write (*args_ind[af_index]));
      args[af_index] = *args_ind[af_index];
   }
   else
   {
        zval* arg;
  if (local_TLE14 == NULL)
    arg = EG (uninitialized_zval_ptr);
  else
    arg = local_TLE14;

      args[af_index] = fetch_var_arg (arg, &destruct[af_index]);
      args_ind[af_index] = &args[af_index];
   }
   af_index++;
   destruct[af_index] = 0;
   if (by_ref[af_index])
   {
        if (local_TLE15 == NULL)
    {
      local_TLE15 = EG (uninitialized_zval_ptr);
      local_TLE15->refcount++;
    }
  zval** p_arg = &local_TLE15;

      args_ind[af_index] = fetch_var_arg_by_ref (p_arg);
      assert (!in_copy_on_write (*args_ind[af_index]));
      args[af_index] = *args_ind[af_index];
   }
   else
   {
        zval* arg;
  if (local_TLE15 == NULL)
    arg = EG (uninitialized_zval_ptr);
  else
    arg = local_TLE15;

      args[af_index] = fetch_var_arg (arg, &destruct[af_index]);
      args_ind[af_index] = &args[af_index];
   }
   af_index++;


   phc_setup_error (1, "/home/mdupont/2009/02/introspector/rdfintrospector/mediawiki/trunk/phase3/includes/parser/CoreLinkFunctions.php", 23, NULL TSRMLS_CC);

   // save existing parameters, in case of recursion
   int param_count_save = fci_object.param_count;
   zval*** params_save = fci_object.params;
   zval** retval_save = fci_object.retval_ptr_ptr;

   zval* rhs = NULL;

   // set up params
   fci_object.params = args_ind;
   fci_object.param_count = 5;
   fci_object.retval_ptr_ptr = &rhs;

   // call the function
   int success = zend_call_function (&fci_object, &fcic_object TSRMLS_CC);
   assert(success == SUCCESS);

   // restore params
   fci_object.params = params_save;
   fci_object.param_count = param_count_save;
   fci_object.retval_ptr_ptr = retval_save;

   // unset the errors
   phc_setup_error (0, NULL, 0, NULL TSRMLS_CC);

   int i;
   for (i = 0; i < 5; i++)
   {
      if (destruct[i])
      {
	 assert (destruct[i]);
	 zval_ptr_dtor (args_ind[i]);
      }
   }


   // When the Zend engine returns by reference, it allocates a zval into
   // retval_ptr_ptr. To return by reference, the callee writes into the
   // retval_ptr_ptr, freeing the allocated value as it does.  (Note, it may
   // not actually return anything). So the zval returned - whether we return
   // it, or it is the allocated zval - has a refcount of 1.
 
   // The caller is responsible for cleaning that up (note, this is unaffected
   // by whether it is added to some COW set).

   // For reasons unknown, the Zend API resets the refcount and is_ref fields
   // of the return value after the function returns (unless the callee is
   // interpreted). If the function is supposed to return by reference, this
   // loses the refcount. This only happens when non-interpreted code is
   // called. We work around it, when compiled code is called, by saving the
   // refcount into SAVED_REFCOUNT, in the return statement. The downside is
   // that we may create an error if our code is called by a callback, and
   // returns by reference, and the callback returns by reference. At least
   // this is an obscure case.
   if(signature->common.return_reference && signature->type != ZEND_USER_FUNCTION)
   {
      assert (rhs != EG(uninitialized_zval_ptr));
      rhs->is_ref = 1;
      if (saved_refcount != 0)
      {
	 rhs->refcount = saved_refcount;
      }
      rhs->refcount++;
   }
   saved_refcount = 0; // for 'obscure cases'

        if (local_TLE16 == NULL)
    {
      local_TLE16 = EG (uninitialized_zval_ptr);
      local_TLE16->refcount++;
    }
  zval** p_lhs = &local_TLE16;

   write_var (p_lhs, rhs);


   zval_ptr_dtor (&rhs);
   if(signature->common.return_reference && signature->type != ZEND_USER_FUNCTION)
      zval_ptr_dtor (&rhs);

phc_check_invariants (TSRMLS_C);
}
// return $TLE16;
{
     zval* rhs;
  if (local_TLE16 == NULL)
    rhs = EG (uninitialized_zval_ptr);
  else
    rhs = local_TLE16;

   // Run-time return by reference has different semantics to compile-time.
   // If the function has CTRBR and RTRBR, the the assignment will be
   // reference. If one or the other is return-by-copy, the result will be
   // by copy. Its a question of whether its separated at return-time (which
   // we do here) or at the call-site.
   return_value->value = rhs->value;
   return_value->type = rhs->type;
   zval_copy_ctor (return_value);
   goto end_of_function;
phc_check_invariants (TSRMLS_C);
}
// Method exit
end_of_function:__attribute__((unused));
if (local_TEF1 != NULL)
{
zval_ptr_dtor (&local_TEF1);
}
if (local_TEF2 != NULL)
{
zval_ptr_dtor (&local_TEF2);
}
if (local_TLE0 != NULL)
{
zval_ptr_dtor (&local_TLE0);
}
if (local_TLE10 != NULL)
{
zval_ptr_dtor (&local_TLE10);
}
if (local_TLE11 != NULL)
{
zval_ptr_dtor (&local_TLE11);
}
if (local_TLE12 != NULL)
{
zval_ptr_dtor (&local_TLE12);
}
if (local_TLE13 != NULL)
{
zval_ptr_dtor (&local_TLE13);
}
if (local_TLE14 != NULL)
{
zval_ptr_dtor (&local_TLE14);
}
if (local_TLE15 != NULL)
{
zval_ptr_dtor (&local_TLE15);
}
if (local_TLE16 != NULL)
{
zval_ptr_dtor (&local_TLE16);
}
if (local_displayText != NULL)
{
zval_ptr_dtor (&local_displayText);
}
if (local_holders != NULL)
{
zval_ptr_dtor (&local_holders);
}
if (local_leadingColon != NULL)
{
zval_ptr_dtor (&local_leadingColon);
}
if (local_markers != NULL)
{
zval_ptr_dtor (&local_markers);
}
if (local_parser != NULL)
{
zval_ptr_dtor (&local_parser);
}
if (local_title != NULL)
{
zval_ptr_dtor (&local_title);
}
if (local_titleText != NULL)
{
zval_ptr_dtor (&local_titleText);
}
}
// static function categorylinkhook($parser, $holders, $markers, title $title, $titleText, &$sortText = NULL, &$leadingColon = False)
// {
// 	global $wgContLang;
// 	if (leadingColon) goto L36 else goto L37;
// L36:
// 	$TLE17 = True;
// 	return $TLE17;
// 	goto L38;
// L37:
// 	goto L38;
// L38:
// 	$TLE3 = isset($sortText);
// 	if (TLE3) goto L39 else goto L40;
// L39:
// 	$TEF4 = $markers->findmarker($sortText);
// 	goto L41;
// L40:
// 	$TEF4 = $TLE3;
// 	goto L41;
// L41:
// 	$TLE18 = (bool) $TEF4;
// 	if (TLE18) goto L42 else goto L43;
// L42:
// 	$sortText = $markers->expand($sortText);
// 	$TLE19 = False;
// 	return $TLE19;
// 	goto L44;
// L43:
// 	goto L44;
// L44:
// 	$TLE20 = isset($sortText);
// 	$TLE21 = !$TLE20;
// 	if (TLE21) goto L45 else goto L46;
// L45:
// 	$sortText = $parser->getdefaultsort();
// 	goto L47;
// L46:
// 	goto L47;
// L47:
// 	$sortText = sanitizer::decodecharreferences($sortText);
// 	$TLE22 = '
// ';
// 	$TLE23 = '';
// 	$sortText = str_replace($TLE22, $TLE23, $sortText);
// 	$sortText = $wgContLang->convertcategorykey($sortText);
// 	$TSt24 = $parser->mOutput;
// 	$TLE25 = $title->getdbkey();
// 	$TSt24->addcategory($TLE25, $sortText);
// 	$TLE26 = '';
// 	return $TLE26;
// }
PHP_METHOD(CoreLinkFunctions, categorylinkhook)
{
zval* local_TEF4 = NULL;
zval* local_TLE17 = NULL;
zval* local_TLE18 = NULL;
zval* local_TLE19 = NULL;
zval* local_TLE20 = NULL;
zval* local_TLE21 = NULL;
zval* local_TLE22 = NULL;
zval* local_TLE23 = NULL;
zval* local_TLE25 = NULL;
zval* local_TLE26 = NULL;
zval* local_TLE3 = NULL;
zval* local_TSt24 = NULL;
zval* local_holders = NULL;
zval* local_leadingColon = NULL;
zval* local_markers = NULL;
zval* local_parser = NULL;
zval* local_sortText = NULL;
zval* local_title = NULL;
zval* local_titleText = NULL;
zval* local_wgContLang = NULL;
// Add all parameters as local variables
{
int num_args = ZEND_NUM_ARGS ();
zval* params[7];
zend_get_parameters_array(0, num_args, params);
// param 0
params[0]->refcount++;
if (local_parser != NULL)
{
	zval_ptr_dtor (&local_parser);
}
local_parser = params[0];
// param 1
params[1]->refcount++;
if (local_holders != NULL)
{
	zval_ptr_dtor (&local_holders);
}
local_holders = params[1];
// param 2
params[2]->refcount++;
if (local_markers != NULL)
{
	zval_ptr_dtor (&local_markers);
}
local_markers = params[2];
// param 3
params[3]->refcount++;
if (local_title != NULL)
{
	zval_ptr_dtor (&local_title);
}
local_title = params[3];
// param 4
params[4]->refcount++;
if (local_titleText != NULL)
{
	zval_ptr_dtor (&local_titleText);
}
local_titleText = params[4];
// param 5
if (num_args <= 5)
{
zval* default_value;
{
zval* local___static_value__ = NULL;
// $__static_value__ = NULL;
{
        if (local___static_value__ == NULL)
    {
      local___static_value__ = EG (uninitialized_zval_ptr);
      local___static_value__->refcount++;
    }
  zval** p_lhs = &local___static_value__;

   zval* value;
   if ((*p_lhs)->is_ref)
   {
     // Always overwrite the current value
     value = *p_lhs;
     zval_dtor (value);
   }
   else
   {
     ALLOC_INIT_ZVAL (value);
     zval_ptr_dtor (p_lhs);
     *p_lhs = value;
   }

   ZVAL_NULL (value);

phc_check_invariants (TSRMLS_C);
}
default_value = local___static_value__;
assert(!default_value->is_ref);
default_value->refcount++;
if (local___static_value__ != NULL)
{
zval_ptr_dtor (&local___static_value__);
}
}
default_value->refcount--;
	params[5] = default_value;
}
params[5]->refcount++;
if (local_sortText != NULL)
{
	zval_ptr_dtor (&local_sortText);
}
local_sortText = params[5];
// param 6
if (num_args <= 6)
{
zval* default_value;
{
zval* local___static_value__ = NULL;
// $__static_value__ = False;
{
        if (local___static_value__ == NULL)
    {
      local___static_value__ = EG (uninitialized_zval_ptr);
      local___static_value__->refcount++;
    }
  zval** p_lhs = &local___static_value__;

   zval* value;
   if ((*p_lhs)->is_ref)
   {
     // Always overwrite the current value
     value = *p_lhs;
     zval_dtor (value);
   }
   else
   {
     ALLOC_INIT_ZVAL (value);
     zval_ptr_dtor (p_lhs);
     *p_lhs = value;
   }

   ZVAL_BOOL (value, 0);

phc_check_invariants (TSRMLS_C);
}
default_value = local___static_value__;
assert(!default_value->is_ref);
default_value->refcount++;
if (local___static_value__ != NULL)
{
zval_ptr_dtor (&local___static_value__);
}
}
default_value->refcount--;
	params[6] = default_value;
}
params[6]->refcount++;
if (local_leadingColon != NULL)
{
	zval_ptr_dtor (&local_leadingColon);
}
local_leadingColon = params[6];
}
// Function body
// global $wgContLang;
{
     if (local_wgContLang == NULL)
    {
      local_wgContLang = EG (uninitialized_zval_ptr);
      local_wgContLang->refcount++;
    }
  zval** p_local = &local_wgContLang;

     zval** p_global = get_st_entry (&EG(symbol_table), "wgContLang", 10 + 1, 2660379225u TSRMLS_CC);

   sep_copy_on_write (p_global);
   copy_into_ref (p_local, p_global);
phc_check_invariants (TSRMLS_C);
}
// if (leadingColon) goto L36 else goto L37;
{
     zval* p_cond;
  if (local_leadingColon == NULL)
    p_cond = EG (uninitialized_zval_ptr);
  else
    p_cond = local_leadingColon;

   zend_bool bcond = zend_is_true (p_cond);
   if (bcond)
      goto L36;
   else
      goto L37;
phc_check_invariants (TSRMLS_C);
}
// L36:
L36:;
// $TLE17 = True;
{
        if (local_TLE17 == NULL)
    {
      local_TLE17 = EG (uninitialized_zval_ptr);
      local_TLE17->refcount++;
    }
  zval** p_lhs = &local_TLE17;

   zval* value;
   if ((*p_lhs)->is_ref)
   {
     // Always overwrite the current value
     value = *p_lhs;
     zval_dtor (value);
   }
   else
   {
     ALLOC_INIT_ZVAL (value);
     zval_ptr_dtor (p_lhs);
     *p_lhs = value;
   }

   ZVAL_BOOL (value, 1);

phc_check_invariants (TSRMLS_C);
}
// return $TLE17;
{
     zval* rhs;
  if (local_TLE17 == NULL)
    rhs = EG (uninitialized_zval_ptr);
  else
    rhs = local_TLE17;

   // Run-time return by reference has different semantics to compile-time.
   // If the function has CTRBR and RTRBR, the the assignment will be
   // reference. If one or the other is return-by-copy, the result will be
   // by copy. Its a question of whether its separated at return-time (which
   // we do here) or at the call-site.
   return_value->value = rhs->value;
   return_value->type = rhs->type;
   zval_copy_ctor (return_value);
   goto end_of_function;
phc_check_invariants (TSRMLS_C);
}
// goto L38;
{
goto L38;
phc_check_invariants (TSRMLS_C);
}
// L37:
L37:;
// goto L38;
{
goto L38;
phc_check_invariants (TSRMLS_C);
}
// L38:
L38:;
// $TLE3 = isset($sortText);
{
if (local_TLE3 == NULL)
{
local_TLE3 = EG (uninitialized_zval_ptr);
local_TLE3->refcount++;
}
zval** p_lhs = &local_TLE3;
zval* value;
if ((*p_lhs)->is_ref)
{
  // Always overwrite the current value
  value = *p_lhs;
  zval_dtor (value);
}
else
{
	ALLOC_INIT_ZVAL (value);
	zval_ptr_dtor (p_lhs);
	*p_lhs = value;
}
ZVAL_BOOL(value, local_sortText != NULL && !ZVAL_IS_NULL(local_sortText));
phc_check_invariants (TSRMLS_C);
}
// if (TLE3) goto L39 else goto L40;
{
     zval* p_cond;
  if (local_TLE3 == NULL)
    p_cond = EG (uninitialized_zval_ptr);
  else
    p_cond = local_TLE3;

   zend_bool bcond = zend_is_true (p_cond);
   if (bcond)
      goto L39;
   else
      goto L40;
phc_check_invariants (TSRMLS_C);
}
// L39:
L39:;
// $TEF4 = $markers->findmarker($sortText);
{
     if (local_markers == NULL)
    {
      local_markers = EG (uninitialized_zval_ptr);
      local_markers->refcount++;
    }
  zval** p_obj = &local_markers;

   zend_fcall_info fci_object;
   zend_fcall_info_cache fcic_object = {0, NULL, NULL, NULL};
   initialize_method_call (&fci_object, &fcic_object, p_obj, "findmarker", "/home/mdupont/2009/02/introspector/rdfintrospector/mediawiki/trunk/phase3/includes/parser/CoreLinkFunctions.php", 30 TSRMLS_CC);
      zend_function* signature = fcic_object.function_handler;
   zend_arg_info* arg_info = signature->common.arg_info; // optional

   int by_ref[1];
   int abr_index = 0;
      // TODO: find names to replace index
   if (arg_info)
   {
      by_ref[abr_index] = arg_info->pass_by_reference;
      arg_info++;
   }
   else
      by_ref[abr_index] = signature->common.pass_rest_by_reference;

   abr_index++;


   // Setup array of arguments
   // TODO: i think arrays of size 0 is an error
   int destruct [1];
   zval* args [1];
   zval** args_ind [1];

   int af_index = 0;
      destruct[af_index] = 0;
   if (by_ref[af_index])
   {
        if (local_sortText == NULL)
    {
      local_sortText = EG (uninitialized_zval_ptr);
      local_sortText->refcount++;
    }
  zval** p_arg = &local_sortText;

      args_ind[af_index] = fetch_var_arg_by_ref (p_arg);
      assert (!in_copy_on_write (*args_ind[af_index]));
      args[af_index] = *args_ind[af_index];
   }
   else
   {
        zval* arg;
  if (local_sortText == NULL)
    arg = EG (uninitialized_zval_ptr);
  else
    arg = local_sortText;

      args[af_index] = fetch_var_arg (arg, &destruct[af_index]);
      args_ind[af_index] = &args[af_index];
   }
   af_index++;


   phc_setup_error (1, "/home/mdupont/2009/02/introspector/rdfintrospector/mediawiki/trunk/phase3/includes/parser/CoreLinkFunctions.php", 30, NULL TSRMLS_CC);

   // save existing parameters, in case of recursion
   int param_count_save = fci_object.param_count;
   zval*** params_save = fci_object.params;
   zval** retval_save = fci_object.retval_ptr_ptr;

   zval* rhs = NULL;

   // set up params
   fci_object.params = args_ind;
   fci_object.param_count = 1;
   fci_object.retval_ptr_ptr = &rhs;

   // call the function
   int success = zend_call_function (&fci_object, &fcic_object TSRMLS_CC);
   assert(success == SUCCESS);

   // restore params
   fci_object.params = params_save;
   fci_object.param_count = param_count_save;
   fci_object.retval_ptr_ptr = retval_save;

   // unset the errors
   phc_setup_error (0, NULL, 0, NULL TSRMLS_CC);

   int i;
   for (i = 0; i < 1; i++)
   {
      if (destruct[i])
      {
	 assert (destruct[i]);
	 zval_ptr_dtor (args_ind[i]);
      }
   }


   // When the Zend engine returns by reference, it allocates a zval into
   // retval_ptr_ptr. To return by reference, the callee writes into the
   // retval_ptr_ptr, freeing the allocated value as it does.  (Note, it may
   // not actually return anything). So the zval returned - whether we return
   // it, or it is the allocated zval - has a refcount of 1.
 
   // The caller is responsible for cleaning that up (note, this is unaffected
   // by whether it is added to some COW set).

   // For reasons unknown, the Zend API resets the refcount and is_ref fields
   // of the return value after the function returns (unless the callee is
   // interpreted). If the function is supposed to return by reference, this
   // loses the refcount. This only happens when non-interpreted code is
   // called. We work around it, when compiled code is called, by saving the
   // refcount into SAVED_REFCOUNT, in the return statement. The downside is
   // that we may create an error if our code is called by a callback, and
   // returns by reference, and the callback returns by reference. At least
   // this is an obscure case.
   if(signature->common.return_reference && signature->type != ZEND_USER_FUNCTION)
   {
      assert (rhs != EG(uninitialized_zval_ptr));
      rhs->is_ref = 1;
      if (saved_refcount != 0)
      {
	 rhs->refcount = saved_refcount;
      }
      rhs->refcount++;
   }
   saved_refcount = 0; // for 'obscure cases'

        if (local_TEF4 == NULL)
    {
      local_TEF4 = EG (uninitialized_zval_ptr);
      local_TEF4->refcount++;
    }
  zval** p_lhs = &local_TEF4;

   write_var (p_lhs, rhs);


   zval_ptr_dtor (&rhs);
   if(signature->common.return_reference && signature->type != ZEND_USER_FUNCTION)
      zval_ptr_dtor (&rhs);

phc_check_invariants (TSRMLS_C);
}
// goto L41;
{
goto L41;
phc_check_invariants (TSRMLS_C);
}
// L40:
L40:;
// $TEF4 = $TLE3;
{
    if (local_TEF4 == NULL)
    {
      local_TEF4 = EG (uninitialized_zval_ptr);
      local_TEF4->refcount++;
    }
  zval** p_lhs = &local_TEF4;

    zval* rhs;
  if (local_TLE3 == NULL)
    rhs = EG (uninitialized_zval_ptr);
  else
    rhs = local_TLE3;

  if (*p_lhs != rhs)
    {
        if ((*p_lhs)->is_ref)
      overwrite_lhs (*p_lhs, rhs);
  else
    {
      zval_ptr_dtor (p_lhs);
        if (rhs->is_ref)
    {
      // Take a copy of RHS for LHS
      *p_lhs = zvp_clone_ex (rhs);
    }
  else
    {
      // Share a copy
      rhs->refcount++;
      *p_lhs = rhs;
    }

    }

    }
phc_check_invariants (TSRMLS_C);
}
// goto L41;
{
goto L41;
phc_check_invariants (TSRMLS_C);
}
// L41:
L41:;
// $TLE18 = (bool) $TEF4;
{
      if (local_TLE18 == NULL)
    {
      local_TLE18 = EG (uninitialized_zval_ptr);
      local_TLE18->refcount++;
    }
  zval** p_lhs = &local_TLE18;

    zval* rhs;
  if (local_TEF4 == NULL)
    rhs = EG (uninitialized_zval_ptr);
  else
    rhs = local_TEF4;

  if (*p_lhs != rhs)
    {
        if ((*p_lhs)->is_ref)
      overwrite_lhs (*p_lhs, rhs);
  else
    {
      zval_ptr_dtor (p_lhs);
        if (rhs->is_ref)
    {
      // Take a copy of RHS for LHS
      *p_lhs = zvp_clone_ex (rhs);
    }
  else
    {
      // Share a copy
      rhs->refcount++;
      *p_lhs = rhs;
    }

    }

    }

    assert (IS_BOOL >= 0 && IS_BOOL <= 6);
  if ((*p_lhs)->type != IS_BOOL)
  {
    sep_copy_on_write (p_lhs);
    convert_to_boolean (*p_lhs);
  }

phc_check_invariants (TSRMLS_C);
}
// if (TLE18) goto L42 else goto L43;
{
     zval* p_cond;
  if (local_TLE18 == NULL)
    p_cond = EG (uninitialized_zval_ptr);
  else
    p_cond = local_TLE18;

   zend_bool bcond = zend_is_true (p_cond);
   if (bcond)
      goto L42;
   else
      goto L43;
phc_check_invariants (TSRMLS_C);
}
// L42:
L42:;
// $sortText = $markers->expand($sortText);
{
     if (local_markers == NULL)
    {
      local_markers = EG (uninitialized_zval_ptr);
      local_markers->refcount++;
    }
  zval** p_obj = &local_markers;

   zend_fcall_info fci_object;
   zend_fcall_info_cache fcic_object = {0, NULL, NULL, NULL};
   initialize_method_call (&fci_object, &fcic_object, p_obj, "expand", "/home/mdupont/2009/02/introspector/rdfintrospector/mediawiki/trunk/phase3/includes/parser/CoreLinkFunctions.php", 34 TSRMLS_CC);
      zend_function* signature = fcic_object.function_handler;
   zend_arg_info* arg_info = signature->common.arg_info; // optional

   int by_ref[1];
   int abr_index = 0;
      // TODO: find names to replace index
   if (arg_info)
   {
      by_ref[abr_index] = arg_info->pass_by_reference;
      arg_info++;
   }
   else
      by_ref[abr_index] = signature->common.pass_rest_by_reference;

   abr_index++;


   // Setup array of arguments
   // TODO: i think arrays of size 0 is an error
   int destruct [1];
   zval* args [1];
   zval** args_ind [1];

   int af_index = 0;
      destruct[af_index] = 0;
   if (by_ref[af_index])
   {
        if (local_sortText == NULL)
    {
      local_sortText = EG (uninitialized_zval_ptr);
      local_sortText->refcount++;
    }
  zval** p_arg = &local_sortText;

      args_ind[af_index] = fetch_var_arg_by_ref (p_arg);
      assert (!in_copy_on_write (*args_ind[af_index]));
      args[af_index] = *args_ind[af_index];
   }
   else
   {
        zval* arg;
  if (local_sortText == NULL)
    arg = EG (uninitialized_zval_ptr);
  else
    arg = local_sortText;

      args[af_index] = fetch_var_arg (arg, &destruct[af_index]);
      args_ind[af_index] = &args[af_index];
   }
   af_index++;


   phc_setup_error (1, "/home/mdupont/2009/02/introspector/rdfintrospector/mediawiki/trunk/phase3/includes/parser/CoreLinkFunctions.php", 34, NULL TSRMLS_CC);

   // save existing parameters, in case of recursion
   int param_count_save = fci_object.param_count;
   zval*** params_save = fci_object.params;
   zval** retval_save = fci_object.retval_ptr_ptr;

   zval* rhs = NULL;

   // set up params
   fci_object.params = args_ind;
   fci_object.param_count = 1;
   fci_object.retval_ptr_ptr = &rhs;

   // call the function
   int success = zend_call_function (&fci_object, &fcic_object TSRMLS_CC);
   assert(success == SUCCESS);

   // restore params
   fci_object.params = params_save;
   fci_object.param_count = param_count_save;
   fci_object.retval_ptr_ptr = retval_save;

   // unset the errors
   phc_setup_error (0, NULL, 0, NULL TSRMLS_CC);

   int i;
   for (i = 0; i < 1; i++)
   {
      if (destruct[i])
      {
	 assert (destruct[i]);
	 zval_ptr_dtor (args_ind[i]);
      }
   }


   // When the Zend engine returns by reference, it allocates a zval into
   // retval_ptr_ptr. To return by reference, the callee writes into the
   // retval_ptr_ptr, freeing the allocated value as it does.  (Note, it may
   // not actually return anything). So the zval returned - whether we return
   // it, or it is the allocated zval - has a refcount of 1.
 
   // The caller is responsible for cleaning that up (note, this is unaffected
   // by whether it is added to some COW set).

   // For reasons unknown, the Zend API resets the refcount and is_ref fields
   // of the return value after the function returns (unless the callee is
   // interpreted). If the function is supposed to return by reference, this
   // loses the refcount. This only happens when non-interpreted code is
   // called. We work around it, when compiled code is called, by saving the
   // refcount into SAVED_REFCOUNT, in the return statement. The downside is
   // that we may create an error if our code is called by a callback, and
   // returns by reference, and the callback returns by reference. At least
   // this is an obscure case.
   if(signature->common.return_reference && signature->type != ZEND_USER_FUNCTION)
   {
      assert (rhs != EG(uninitialized_zval_ptr));
      rhs->is_ref = 1;
      if (saved_refcount != 0)
      {
	 rhs->refcount = saved_refcount;
      }
      rhs->refcount++;
   }
   saved_refcount = 0; // for 'obscure cases'

        if (local_sortText == NULL)
    {
      local_sortText = EG (uninitialized_zval_ptr);
      local_sortText->refcount++;
    }
  zval** p_lhs = &local_sortText;

   write_var (p_lhs, rhs);


   zval_ptr_dtor (&rhs);
   if(signature->common.return_reference && signature->type != ZEND_USER_FUNCTION)
      zval_ptr_dtor (&rhs);

phc_check_invariants (TSRMLS_C);
}
// $TLE19 = False;
{
        if (local_TLE19 == NULL)
    {
      local_TLE19 = EG (uninitialized_zval_ptr);
      local_TLE19->refcount++;
    }
  zval** p_lhs = &local_TLE19;

   zval* value;
   if ((*p_lhs)->is_ref)
   {
     // Always overwrite the current value
     value = *p_lhs;
     zval_dtor (value);
   }
   else
   {
     ALLOC_INIT_ZVAL (value);
     zval_ptr_dtor (p_lhs);
     *p_lhs = value;
   }

   ZVAL_BOOL (value, 0);

phc_check_invariants (TSRMLS_C);
}
// return $TLE19;
{
     zval* rhs;
  if (local_TLE19 == NULL)
    rhs = EG (uninitialized_zval_ptr);
  else
    rhs = local_TLE19;

   // Run-time return by reference has different semantics to compile-time.
   // If the function has CTRBR and RTRBR, the the assignment will be
   // reference. If one or the other is return-by-copy, the result will be
   // by copy. Its a question of whether its separated at return-time (which
   // we do here) or at the call-site.
   return_value->value = rhs->value;
   return_value->type = rhs->type;
   zval_copy_ctor (return_value);
   goto end_of_function;
phc_check_invariants (TSRMLS_C);
}
// goto L44;
{
goto L44;
phc_check_invariants (TSRMLS_C);
}
// L43:
L43:;
// goto L44;
{
goto L44;
phc_check_invariants (TSRMLS_C);
}
// L44:
L44:;
// $TLE20 = isset($sortText);
{
if (local_TLE20 == NULL)
{
local_TLE20 = EG (uninitialized_zval_ptr);
local_TLE20->refcount++;
}
zval** p_lhs = &local_TLE20;
zval* value;
if ((*p_lhs)->is_ref)
{
  // Always overwrite the current value
  value = *p_lhs;
  zval_dtor (value);
}
else
{
	ALLOC_INIT_ZVAL (value);
	zval_ptr_dtor (p_lhs);
	*p_lhs = value;
}
ZVAL_BOOL(value, local_sortText != NULL && !ZVAL_IS_NULL(local_sortText));
phc_check_invariants (TSRMLS_C);
}
// $TLE21 = !$TLE20;
{
     if (local_TLE21 == NULL)
    {
      local_TLE21 = EG (uninitialized_zval_ptr);
      local_TLE21->refcount++;
    }
  zval** p_lhs = &local_TLE21;

     zval* rhs;
  if (local_TLE20 == NULL)
    rhs = EG (uninitialized_zval_ptr);
  else
    rhs = local_TLE20;

   if (in_copy_on_write (*p_lhs))
   {
     zval_ptr_dtor (p_lhs);
     ALLOC_INIT_ZVAL (*p_lhs);
   }

   zval old = **p_lhs;
   int result_is_operand = (*p_lhs == rhs);
   boolean_not_function (*p_lhs, rhs TSRMLS_CC);
   if (!result_is_operand)
	zval_dtor (&old);
phc_check_invariants (TSRMLS_C);
}
// if (TLE21) goto L45 else goto L46;
{
     zval* p_cond;
  if (local_TLE21 == NULL)
    p_cond = EG (uninitialized_zval_ptr);
  else
    p_cond = local_TLE21;

   zend_bool bcond = zend_is_true (p_cond);
   if (bcond)
      goto L45;
   else
      goto L46;
phc_check_invariants (TSRMLS_C);
}
// L45:
L45:;
// $sortText = $parser->getdefaultsort();
{
     if (local_parser == NULL)
    {
      local_parser = EG (uninitialized_zval_ptr);
      local_parser->refcount++;
    }
  zval** p_obj = &local_parser;

   zend_fcall_info fci_object;
   zend_fcall_info_cache fcic_object = {0, NULL, NULL, NULL};
   initialize_method_call (&fci_object, &fcic_object, p_obj, "getdefaultsort", "/home/mdupont/2009/02/introspector/rdfintrospector/mediawiki/trunk/phase3/includes/parser/CoreLinkFunctions.php", 38 TSRMLS_CC);
      zend_function* signature = fcic_object.function_handler;
   zend_arg_info* arg_info = signature->common.arg_info; // optional

   int by_ref[0];
   int abr_index = 0;
   

   // Setup array of arguments
   // TODO: i think arrays of size 0 is an error
   int destruct [0];
   zval* args [0];
   zval** args_ind [0];

   int af_index = 0;
   

   phc_setup_error (1, "/home/mdupont/2009/02/introspector/rdfintrospector/mediawiki/trunk/phase3/includes/parser/CoreLinkFunctions.php", 38, NULL TSRMLS_CC);

   // save existing parameters, in case of recursion
   int param_count_save = fci_object.param_count;
   zval*** params_save = fci_object.params;
   zval** retval_save = fci_object.retval_ptr_ptr;

   zval* rhs = NULL;

   // set up params
   fci_object.params = args_ind;
   fci_object.param_count = 0;
   fci_object.retval_ptr_ptr = &rhs;

   // call the function
   int success = zend_call_function (&fci_object, &fcic_object TSRMLS_CC);
   assert(success == SUCCESS);

   // restore params
   fci_object.params = params_save;
   fci_object.param_count = param_count_save;
   fci_object.retval_ptr_ptr = retval_save;

   // unset the errors
   phc_setup_error (0, NULL, 0, NULL TSRMLS_CC);

   int i;
   for (i = 0; i < 0; i++)
   {
      if (destruct[i])
      {
	 assert (destruct[i]);
	 zval_ptr_dtor (args_ind[i]);
      }
   }


   // When the Zend engine returns by reference, it allocates a zval into
   // retval_ptr_ptr. To return by reference, the callee writes into the
   // retval_ptr_ptr, freeing the allocated value as it does.  (Note, it may
   // not actually return anything). So the zval returned - whether we return
   // it, or it is the allocated zval - has a refcount of 1.
 
   // The caller is responsible for cleaning that up (note, this is unaffected
   // by whether it is added to some COW set).

   // For reasons unknown, the Zend API resets the refcount and is_ref fields
   // of the return value after the function returns (unless the callee is
   // interpreted). If the function is supposed to return by reference, this
   // loses the refcount. This only happens when non-interpreted code is
   // called. We work around it, when compiled code is called, by saving the
   // refcount into SAVED_REFCOUNT, in the return statement. The downside is
   // that we may create an error if our code is called by a callback, and
   // returns by reference, and the callback returns by reference. At least
   // this is an obscure case.
   if(signature->common.return_reference && signature->type != ZEND_USER_FUNCTION)
   {
      assert (rhs != EG(uninitialized_zval_ptr));
      rhs->is_ref = 1;
      if (saved_refcount != 0)
      {
	 rhs->refcount = saved_refcount;
      }
      rhs->refcount++;
   }
   saved_refcount = 0; // for 'obscure cases'

        if (local_sortText == NULL)
    {
      local_sortText = EG (uninitialized_zval_ptr);
      local_sortText->refcount++;
    }
  zval** p_lhs = &local_sortText;

   write_var (p_lhs, rhs);


   zval_ptr_dtor (&rhs);
   if(signature->common.return_reference && signature->type != ZEND_USER_FUNCTION)
      zval_ptr_dtor (&rhs);

phc_check_invariants (TSRMLS_C);
}
// goto L47;
{
goto L47;
phc_check_invariants (TSRMLS_C);
}
// L46:
L46:;
// goto L47;
{
goto L47;
phc_check_invariants (TSRMLS_C);
}
// L47:
L47:;
// $sortText = sanitizer::decodecharreferences($sortText);
{
   initialize_function_call (&sanitizer_decodecharreferences_fci, &sanitizer_decodecharreferences_fcic, "sanitizer::decodecharreferences", "/home/mdupont/2009/02/introspector/rdfintrospector/mediawiki/trunk/phase3/includes/parser/CoreLinkFunctions.php", 39 TSRMLS_CC);
      zend_function* signature = sanitizer_decodecharreferences_fcic.function_handler;
   zend_arg_info* arg_info = signature->common.arg_info; // optional

   int by_ref[1];
   int abr_index = 0;
      // TODO: find names to replace index
   if (arg_info)
   {
      by_ref[abr_index] = arg_info->pass_by_reference;
      arg_info++;
   }
   else
      by_ref[abr_index] = signature->common.pass_rest_by_reference;

   abr_index++;


   // Setup array of arguments
   // TODO: i think arrays of size 0 is an error
   int destruct [1];
   zval* args [1];
   zval** args_ind [1];

   int af_index = 0;
      destruct[af_index] = 0;
   if (by_ref[af_index])
   {
        if (local_sortText == NULL)
    {
      local_sortText = EG (uninitialized_zval_ptr);
      local_sortText->refcount++;
    }
  zval** p_arg = &local_sortText;

      args_ind[af_index] = fetch_var_arg_by_ref (p_arg);
      assert (!in_copy_on_write (*args_ind[af_index]));
      args[af_index] = *args_ind[af_index];
   }
   else
   {
        zval* arg;
  if (local_sortText == NULL)
    arg = EG (uninitialized_zval_ptr);
  else
    arg = local_sortText;

      args[af_index] = fetch_var_arg (arg, &destruct[af_index]);
      args_ind[af_index] = &args[af_index];
   }
   af_index++;


   phc_setup_error (1, "/home/mdupont/2009/02/introspector/rdfintrospector/mediawiki/trunk/phase3/includes/parser/CoreLinkFunctions.php", 39, NULL TSRMLS_CC);

   // save existing parameters, in case of recursion
   int param_count_save = sanitizer_decodecharreferences_fci.param_count;
   zval*** params_save = sanitizer_decodecharreferences_fci.params;
   zval** retval_save = sanitizer_decodecharreferences_fci.retval_ptr_ptr;

   zval* rhs = NULL;

   // set up params
   sanitizer_decodecharreferences_fci.params = args_ind;
   sanitizer_decodecharreferences_fci.param_count = 1;
   sanitizer_decodecharreferences_fci.retval_ptr_ptr = &rhs;

   // call the function
   int success = zend_call_function (&sanitizer_decodecharreferences_fci, &sanitizer_decodecharreferences_fcic TSRMLS_CC);
   assert(success == SUCCESS);

   // restore params
   sanitizer_decodecharreferences_fci.params = params_save;
   sanitizer_decodecharreferences_fci.param_count = param_count_save;
   sanitizer_decodecharreferences_fci.retval_ptr_ptr = retval_save;

   // unset the errors
   phc_setup_error (0, NULL, 0, NULL TSRMLS_CC);

   int i;
   for (i = 0; i < 1; i++)
   {
      if (destruct[i])
      {
	 assert (destruct[i]);
	 zval_ptr_dtor (args_ind[i]);
      }
   }


   // When the Zend engine returns by reference, it allocates a zval into
   // retval_ptr_ptr. To return by reference, the callee writes into the
   // retval_ptr_ptr, freeing the allocated value as it does.  (Note, it may
   // not actually return anything). So the zval returned - whether we return
   // it, or it is the allocated zval - has a refcount of 1.
 
   // The caller is responsible for cleaning that up (note, this is unaffected
   // by whether it is added to some COW set).

   // For reasons unknown, the Zend API resets the refcount and is_ref fields
   // of the return value after the function returns (unless the callee is
   // interpreted). If the function is supposed to return by reference, this
   // loses the refcount. This only happens when non-interpreted code is
   // called. We work around it, when compiled code is called, by saving the
   // refcount into SAVED_REFCOUNT, in the return statement. The downside is
   // that we may create an error if our code is called by a callback, and
   // returns by reference, and the callback returns by reference. At least
   // this is an obscure case.
   if(signature->common.return_reference && signature->type != ZEND_USER_FUNCTION)
   {
      assert (rhs != EG(uninitialized_zval_ptr));
      rhs->is_ref = 1;
      if (saved_refcount != 0)
      {
	 rhs->refcount = saved_refcount;
      }
      rhs->refcount++;
   }
   saved_refcount = 0; // for 'obscure cases'

        if (local_sortText == NULL)
    {
      local_sortText = EG (uninitialized_zval_ptr);
      local_sortText->refcount++;
    }
  zval** p_lhs = &local_sortText;

   write_var (p_lhs, rhs);


   zval_ptr_dtor (&rhs);
   if(signature->common.return_reference && signature->type != ZEND_USER_FUNCTION)
      zval_ptr_dtor (&rhs);

phc_check_invariants (TSRMLS_C);
}
// $TLE22 = '
// ';
{
        if (local_TLE22 == NULL)
    {
      local_TLE22 = EG (uninitialized_zval_ptr);
      local_TLE22->refcount++;
    }
  zval** p_lhs = &local_TLE22;

   zval* value;
   if ((*p_lhs)->is_ref)
   {
     // Always overwrite the current value
     value = *p_lhs;
     zval_dtor (value);
   }
   else
   {
     ALLOC_INIT_ZVAL (value);
     zval_ptr_dtor (p_lhs);
     *p_lhs = value;
   }

   ZVAL_STRINGL(value, "\012", 1, 1);

phc_check_invariants (TSRMLS_C);
}
// $TLE23 = '';
{
        if (local_TLE23 == NULL)
    {
      local_TLE23 = EG (uninitialized_zval_ptr);
      local_TLE23->refcount++;
    }
  zval** p_lhs = &local_TLE23;

   zval* value;
   if ((*p_lhs)->is_ref)
   {
     // Always overwrite the current value
     value = *p_lhs;
     zval_dtor (value);
   }
   else
   {
     ALLOC_INIT_ZVAL (value);
     zval_ptr_dtor (p_lhs);
     *p_lhs = value;
   }

   ZVAL_STRINGL(value, "", 0, 1);

phc_check_invariants (TSRMLS_C);
}
// $sortText = str_replace($TLE22, $TLE23, $sortText);
{
   initialize_function_call (&str_replace_fci, &str_replace_fcic, "str_replace", "/home/mdupont/2009/02/introspector/rdfintrospector/mediawiki/trunk/phase3/includes/parser/CoreLinkFunctions.php", 40 TSRMLS_CC);
      zend_function* signature = str_replace_fcic.function_handler;
   zend_arg_info* arg_info = signature->common.arg_info; // optional

   int by_ref[3];
   int abr_index = 0;
      // TODO: find names to replace index
   if (arg_info)
   {
      by_ref[abr_index] = arg_info->pass_by_reference;
      arg_info++;
   }
   else
      by_ref[abr_index] = signature->common.pass_rest_by_reference;

   abr_index++;
   // TODO: find names to replace index
   if (arg_info)
   {
      by_ref[abr_index] = arg_info->pass_by_reference;
      arg_info++;
   }
   else
      by_ref[abr_index] = signature->common.pass_rest_by_reference;

   abr_index++;
   // TODO: find names to replace index
   if (arg_info)
   {
      by_ref[abr_index] = arg_info->pass_by_reference;
      arg_info++;
   }
   else
      by_ref[abr_index] = signature->common.pass_rest_by_reference;

   abr_index++;


   // Setup array of arguments
   // TODO: i think arrays of size 0 is an error
   int destruct [3];
   zval* args [3];
   zval** args_ind [3];

   int af_index = 0;
      destruct[af_index] = 0;
   if (by_ref[af_index])
   {
        if (local_TLE22 == NULL)
    {
      local_TLE22 = EG (uninitialized_zval_ptr);
      local_TLE22->refcount++;
    }
  zval** p_arg = &local_TLE22;

      args_ind[af_index] = fetch_var_arg_by_ref (p_arg);
      assert (!in_copy_on_write (*args_ind[af_index]));
      args[af_index] = *args_ind[af_index];
   }
   else
   {
        zval* arg;
  if (local_TLE22 == NULL)
    arg = EG (uninitialized_zval_ptr);
  else
    arg = local_TLE22;

      args[af_index] = fetch_var_arg (arg, &destruct[af_index]);
      args_ind[af_index] = &args[af_index];
   }
   af_index++;
   destruct[af_index] = 0;
   if (by_ref[af_index])
   {
        if (local_TLE23 == NULL)
    {
      local_TLE23 = EG (uninitialized_zval_ptr);
      local_TLE23->refcount++;
    }
  zval** p_arg = &local_TLE23;

      args_ind[af_index] = fetch_var_arg_by_ref (p_arg);
      assert (!in_copy_on_write (*args_ind[af_index]));
      args[af_index] = *args_ind[af_index];
   }
   else
   {
        zval* arg;
  if (local_TLE23 == NULL)
    arg = EG (uninitialized_zval_ptr);
  else
    arg = local_TLE23;

      args[af_index] = fetch_var_arg (arg, &destruct[af_index]);
      args_ind[af_index] = &args[af_index];
   }
   af_index++;
   destruct[af_index] = 0;
   if (by_ref[af_index])
   {
        if (local_sortText == NULL)
    {
      local_sortText = EG (uninitialized_zval_ptr);
      local_sortText->refcount++;
    }
  zval** p_arg = &local_sortText;

      args_ind[af_index] = fetch_var_arg_by_ref (p_arg);
      assert (!in_copy_on_write (*args_ind[af_index]));
      args[af_index] = *args_ind[af_index];
   }
   else
   {
        zval* arg;
  if (local_sortText == NULL)
    arg = EG (uninitialized_zval_ptr);
  else
    arg = local_sortText;

      args[af_index] = fetch_var_arg (arg, &destruct[af_index]);
      args_ind[af_index] = &args[af_index];
   }
   af_index++;


   phc_setup_error (1, "/home/mdupont/2009/02/introspector/rdfintrospector/mediawiki/trunk/phase3/includes/parser/CoreLinkFunctions.php", 40, NULL TSRMLS_CC);

   // save existing parameters, in case of recursion
   int param_count_save = str_replace_fci.param_count;
   zval*** params_save = str_replace_fci.params;
   zval** retval_save = str_replace_fci.retval_ptr_ptr;

   zval* rhs = NULL;

   // set up params
   str_replace_fci.params = args_ind;
   str_replace_fci.param_count = 3;
   str_replace_fci.retval_ptr_ptr = &rhs;

   // call the function
   int success = zend_call_function (&str_replace_fci, &str_replace_fcic TSRMLS_CC);
   assert(success == SUCCESS);

   // restore params
   str_replace_fci.params = params_save;
   str_replace_fci.param_count = param_count_save;
   str_replace_fci.retval_ptr_ptr = retval_save;

   // unset the errors
   phc_setup_error (0, NULL, 0, NULL TSRMLS_CC);

   int i;
   for (i = 0; i < 3; i++)
   {
      if (destruct[i])
      {
	 assert (destruct[i]);
	 zval_ptr_dtor (args_ind[i]);
      }
   }


   // When the Zend engine returns by reference, it allocates a zval into
   // retval_ptr_ptr. To return by reference, the callee writes into the
   // retval_ptr_ptr, freeing the allocated value as it does.  (Note, it may
   // not actually return anything). So the zval returned - whether we return
   // it, or it is the allocated zval - has a refcount of 1.
 
   // The caller is responsible for cleaning that up (note, this is unaffected
   // by whether it is added to some COW set).

   // For reasons unknown, the Zend API resets the refcount and is_ref fields
   // of the return value after the function returns (unless the callee is
   // interpreted). If the function is supposed to return by reference, this
   // loses the refcount. This only happens when non-interpreted code is
   // called. We work around it, when compiled code is called, by saving the
   // refcount into SAVED_REFCOUNT, in the return statement. The downside is
   // that we may create an error if our code is called by a callback, and
   // returns by reference, and the callback returns by reference. At least
   // this is an obscure case.
   if(signature->common.return_reference && signature->type != ZEND_USER_FUNCTION)
   {
      assert (rhs != EG(uninitialized_zval_ptr));
      rhs->is_ref = 1;
      if (saved_refcount != 0)
      {
	 rhs->refcount = saved_refcount;
      }
      rhs->refcount++;
   }
   saved_refcount = 0; // for 'obscure cases'

        if (local_sortText == NULL)
    {
      local_sortText = EG (uninitialized_zval_ptr);
      local_sortText->refcount++;
    }
  zval** p_lhs = &local_sortText;

   write_var (p_lhs, rhs);


   zval_ptr_dtor (&rhs);
   if(signature->common.return_reference && signature->type != ZEND_USER_FUNCTION)
      zval_ptr_dtor (&rhs);

phc_check_invariants (TSRMLS_C);
}
// $sortText = $wgContLang->convertcategorykey($sortText);
{
     if (local_wgContLang == NULL)
    {
      local_wgContLang = EG (uninitialized_zval_ptr);
      local_wgContLang->refcount++;
    }
  zval** p_obj = &local_wgContLang;

   zend_fcall_info fci_object;
   zend_fcall_info_cache fcic_object = {0, NULL, NULL, NULL};
   initialize_method_call (&fci_object, &fcic_object, p_obj, "convertcategorykey", "/home/mdupont/2009/02/introspector/rdfintrospector/mediawiki/trunk/phase3/includes/parser/CoreLinkFunctions.php", 41 TSRMLS_CC);
      zend_function* signature = fcic_object.function_handler;
   zend_arg_info* arg_info = signature->common.arg_info; // optional

   int by_ref[1];
   int abr_index = 0;
      // TODO: find names to replace index
   if (arg_info)
   {
      by_ref[abr_index] = arg_info->pass_by_reference;
      arg_info++;
   }
   else
      by_ref[abr_index] = signature->common.pass_rest_by_reference;

   abr_index++;


   // Setup array of arguments
   // TODO: i think arrays of size 0 is an error
   int destruct [1];
   zval* args [1];
   zval** args_ind [1];

   int af_index = 0;
      destruct[af_index] = 0;
   if (by_ref[af_index])
   {
        if (local_sortText == NULL)
    {
      local_sortText = EG (uninitialized_zval_ptr);
      local_sortText->refcount++;
    }
  zval** p_arg = &local_sortText;

      args_ind[af_index] = fetch_var_arg_by_ref (p_arg);
      assert (!in_copy_on_write (*args_ind[af_index]));
      args[af_index] = *args_ind[af_index];
   }
   else
   {
        zval* arg;
  if (local_sortText == NULL)
    arg = EG (uninitialized_zval_ptr);
  else
    arg = local_sortText;

      args[af_index] = fetch_var_arg (arg, &destruct[af_index]);
      args_ind[af_index] = &args[af_index];
   }
   af_index++;


   phc_setup_error (1, "/home/mdupont/2009/02/introspector/rdfintrospector/mediawiki/trunk/phase3/includes/parser/CoreLinkFunctions.php", 41, NULL TSRMLS_CC);

   // save existing parameters, in case of recursion
   int param_count_save = fci_object.param_count;
   zval*** params_save = fci_object.params;
   zval** retval_save = fci_object.retval_ptr_ptr;

   zval* rhs = NULL;

   // set up params
   fci_object.params = args_ind;
   fci_object.param_count = 1;
   fci_object.retval_ptr_ptr = &rhs;

   // call the function
   int success = zend_call_function (&fci_object, &fcic_object TSRMLS_CC);
   assert(success == SUCCESS);

   // restore params
   fci_object.params = params_save;
   fci_object.param_count = param_count_save;
   fci_object.retval_ptr_ptr = retval_save;

   // unset the errors
   phc_setup_error (0, NULL, 0, NULL TSRMLS_CC);

   int i;
   for (i = 0; i < 1; i++)
   {
      if (destruct[i])
      {
	 assert (destruct[i]);
	 zval_ptr_dtor (args_ind[i]);
      }
   }


   // When the Zend engine returns by reference, it allocates a zval into
   // retval_ptr_ptr. To return by reference, the callee writes into the
   // retval_ptr_ptr, freeing the allocated value as it does.  (Note, it may
   // not actually return anything). So the zval returned - whether we return
   // it, or it is the allocated zval - has a refcount of 1.
 
   // The caller is responsible for cleaning that up (note, this is unaffected
   // by whether it is added to some COW set).

   // For reasons unknown, the Zend API resets the refcount and is_ref fields
   // of the return value after the function returns (unless the callee is
   // interpreted). If the function is supposed to return by reference, this
   // loses the refcount. This only happens when non-interpreted code is
   // called. We work around it, when compiled code is called, by saving the
   // refcount into SAVED_REFCOUNT, in the return statement. The downside is
   // that we may create an error if our code is called by a callback, and
   // returns by reference, and the callback returns by reference. At least
   // this is an obscure case.
   if(signature->common.return_reference && signature->type != ZEND_USER_FUNCTION)
   {
      assert (rhs != EG(uninitialized_zval_ptr));
      rhs->is_ref = 1;
      if (saved_refcount != 0)
      {
	 rhs->refcount = saved_refcount;
      }
      rhs->refcount++;
   }
   saved_refcount = 0; // for 'obscure cases'

        if (local_sortText == NULL)
    {
      local_sortText = EG (uninitialized_zval_ptr);
      local_sortText->refcount++;
    }
  zval** p_lhs = &local_sortText;

   write_var (p_lhs, rhs);


   zval_ptr_dtor (&rhs);
   if(signature->common.return_reference && signature->type != ZEND_USER_FUNCTION)
      zval_ptr_dtor (&rhs);

phc_check_invariants (TSRMLS_C);
}
// $TSt24 = $parser->mOutput;
{
	  if (local_parser == NULL)
    {
      local_parser = EG (uninitialized_zval_ptr);
      local_parser->refcount++;
    }
  zval** p_obj = &local_parser;

		zval field_name;
	INIT_ZVAL (field_name);
	ZVAL_STRING (&field_name, "mOutput", 0);

	// I *think* this is correct, but documentation of the Zend API is scarce :)
	zval* field = Z_OBJ_HT_PP(p_obj)->read_property(*p_obj, &field_name, BP_VAR_R TSRMLS_CC);
	  if (local_TSt24 == NULL)
    {
      local_TSt24 = EG (uninitialized_zval_ptr);
      local_TSt24->refcount++;
    }
  zval** p_lhs = &local_TSt24;

	write_var (p_lhs, field); 
phc_check_invariants (TSRMLS_C);
}
// $TLE25 = $title->getdbkey();
{
     if (local_title == NULL)
    {
      local_title = EG (uninitialized_zval_ptr);
      local_title->refcount++;
    }
  zval** p_obj = &local_title;

   zend_fcall_info fci_object;
   zend_fcall_info_cache fcic_object = {0, NULL, NULL, NULL};
   initialize_method_call (&fci_object, &fcic_object, p_obj, "getdbkey", "/home/mdupont/2009/02/introspector/rdfintrospector/mediawiki/trunk/phase3/includes/parser/CoreLinkFunctions.php", 42 TSRMLS_CC);
      zend_function* signature = fcic_object.function_handler;
   zend_arg_info* arg_info = signature->common.arg_info; // optional

   int by_ref[0];
   int abr_index = 0;
   

   // Setup array of arguments
   // TODO: i think arrays of size 0 is an error
   int destruct [0];
   zval* args [0];
   zval** args_ind [0];

   int af_index = 0;
   

   phc_setup_error (1, "/home/mdupont/2009/02/introspector/rdfintrospector/mediawiki/trunk/phase3/includes/parser/CoreLinkFunctions.php", 42, NULL TSRMLS_CC);

   // save existing parameters, in case of recursion
   int param_count_save = fci_object.param_count;
   zval*** params_save = fci_object.params;
   zval** retval_save = fci_object.retval_ptr_ptr;

   zval* rhs = NULL;

   // set up params
   fci_object.params = args_ind;
   fci_object.param_count = 0;
   fci_object.retval_ptr_ptr = &rhs;

   // call the function
   int success = zend_call_function (&fci_object, &fcic_object TSRMLS_CC);
   assert(success == SUCCESS);

   // restore params
   fci_object.params = params_save;
   fci_object.param_count = param_count_save;
   fci_object.retval_ptr_ptr = retval_save;

   // unset the errors
   phc_setup_error (0, NULL, 0, NULL TSRMLS_CC);

   int i;
   for (i = 0; i < 0; i++)
   {
      if (destruct[i])
      {
	 assert (destruct[i]);
	 zval_ptr_dtor (args_ind[i]);
      }
   }


   // When the Zend engine returns by reference, it allocates a zval into
   // retval_ptr_ptr. To return by reference, the callee writes into the
   // retval_ptr_ptr, freeing the allocated value as it does.  (Note, it may
   // not actually return anything). So the zval returned - whether we return
   // it, or it is the allocated zval - has a refcount of 1.
 
   // The caller is responsible for cleaning that up (note, this is unaffected
   // by whether it is added to some COW set).

   // For reasons unknown, the Zend API resets the refcount and is_ref fields
   // of the return value after the function returns (unless the callee is
   // interpreted). If the function is supposed to return by reference, this
   // loses the refcount. This only happens when non-interpreted code is
   // called. We work around it, when compiled code is called, by saving the
   // refcount into SAVED_REFCOUNT, in the return statement. The downside is
   // that we may create an error if our code is called by a callback, and
   // returns by reference, and the callback returns by reference. At least
   // this is an obscure case.
   if(signature->common.return_reference && signature->type != ZEND_USER_FUNCTION)
   {
      assert (rhs != EG(uninitialized_zval_ptr));
      rhs->is_ref = 1;
      if (saved_refcount != 0)
      {
	 rhs->refcount = saved_refcount;
      }
      rhs->refcount++;
   }
   saved_refcount = 0; // for 'obscure cases'

        if (local_TLE25 == NULL)
    {
      local_TLE25 = EG (uninitialized_zval_ptr);
      local_TLE25->refcount++;
    }
  zval** p_lhs = &local_TLE25;

   write_var (p_lhs, rhs);


   zval_ptr_dtor (&rhs);
   if(signature->common.return_reference && signature->type != ZEND_USER_FUNCTION)
      zval_ptr_dtor (&rhs);

phc_check_invariants (TSRMLS_C);
}
// $TSt24->addcategory($TLE25, $sortText);
{
     if (local_TSt24 == NULL)
    {
      local_TSt24 = EG (uninitialized_zval_ptr);
      local_TSt24->refcount++;
    }
  zval** p_obj = &local_TSt24;

   zend_fcall_info fci_object;
   zend_fcall_info_cache fcic_object = {0, NULL, NULL, NULL};
   initialize_method_call (&fci_object, &fcic_object, p_obj, "addcategory", "/home/mdupont/2009/02/introspector/rdfintrospector/mediawiki/trunk/phase3/includes/parser/CoreLinkFunctions.php", 42 TSRMLS_CC);
      zend_function* signature = fcic_object.function_handler;
   zend_arg_info* arg_info = signature->common.arg_info; // optional

   int by_ref[2];
   int abr_index = 0;
      // TODO: find names to replace index
   if (arg_info)
   {
      by_ref[abr_index] = arg_info->pass_by_reference;
      arg_info++;
   }
   else
      by_ref[abr_index] = signature->common.pass_rest_by_reference;

   abr_index++;
   // TODO: find names to replace index
   if (arg_info)
   {
      by_ref[abr_index] = arg_info->pass_by_reference;
      arg_info++;
   }
   else
      by_ref[abr_index] = signature->common.pass_rest_by_reference;

   abr_index++;


   // Setup array of arguments
   // TODO: i think arrays of size 0 is an error
   int destruct [2];
   zval* args [2];
   zval** args_ind [2];

   int af_index = 0;
      destruct[af_index] = 0;
   if (by_ref[af_index])
   {
        if (local_TLE25 == NULL)
    {
      local_TLE25 = EG (uninitialized_zval_ptr);
      local_TLE25->refcount++;
    }
  zval** p_arg = &local_TLE25;

      args_ind[af_index] = fetch_var_arg_by_ref (p_arg);
      assert (!in_copy_on_write (*args_ind[af_index]));
      args[af_index] = *args_ind[af_index];
   }
   else
   {
        zval* arg;
  if (local_TLE25 == NULL)
    arg = EG (uninitialized_zval_ptr);
  else
    arg = local_TLE25;

      args[af_index] = fetch_var_arg (arg, &destruct[af_index]);
      args_ind[af_index] = &args[af_index];
   }
   af_index++;
   destruct[af_index] = 0;
   if (by_ref[af_index])
   {
        if (local_sortText == NULL)
    {
      local_sortText = EG (uninitialized_zval_ptr);
      local_sortText->refcount++;
    }
  zval** p_arg = &local_sortText;

      args_ind[af_index] = fetch_var_arg_by_ref (p_arg);
      assert (!in_copy_on_write (*args_ind[af_index]));
      args[af_index] = *args_ind[af_index];
   }
   else
   {
        zval* arg;
  if (local_sortText == NULL)
    arg = EG (uninitialized_zval_ptr);
  else
    arg = local_sortText;

      args[af_index] = fetch_var_arg (arg, &destruct[af_index]);
      args_ind[af_index] = &args[af_index];
   }
   af_index++;


   phc_setup_error (1, "/home/mdupont/2009/02/introspector/rdfintrospector/mediawiki/trunk/phase3/includes/parser/CoreLinkFunctions.php", 42, NULL TSRMLS_CC);

   // save existing parameters, in case of recursion
   int param_count_save = fci_object.param_count;
   zval*** params_save = fci_object.params;
   zval** retval_save = fci_object.retval_ptr_ptr;

   zval* rhs = NULL;

   // set up params
   fci_object.params = args_ind;
   fci_object.param_count = 2;
   fci_object.retval_ptr_ptr = &rhs;

   // call the function
   int success = zend_call_function (&fci_object, &fcic_object TSRMLS_CC);
   assert(success == SUCCESS);

   // restore params
   fci_object.params = params_save;
   fci_object.param_count = param_count_save;
   fci_object.retval_ptr_ptr = retval_save;

   // unset the errors
   phc_setup_error (0, NULL, 0, NULL TSRMLS_CC);

   int i;
   for (i = 0; i < 2; i++)
   {
      if (destruct[i])
      {
	 assert (destruct[i]);
	 zval_ptr_dtor (args_ind[i]);
      }
   }


   // When the Zend engine returns by reference, it allocates a zval into
   // retval_ptr_ptr. To return by reference, the callee writes into the
   // retval_ptr_ptr, freeing the allocated value as it does.  (Note, it may
   // not actually return anything). So the zval returned - whether we return
   // it, or it is the allocated zval - has a refcount of 1.
 
   // The caller is responsible for cleaning that up (note, this is unaffected
   // by whether it is added to some COW set).

   // For reasons unknown, the Zend API resets the refcount and is_ref fields
   // of the return value after the function returns (unless the callee is
   // interpreted). If the function is supposed to return by reference, this
   // loses the refcount. This only happens when non-interpreted code is
   // called. We work around it, when compiled code is called, by saving the
   // refcount into SAVED_REFCOUNT, in the return statement. The downside is
   // that we may create an error if our code is called by a callback, and
   // returns by reference, and the callback returns by reference. At least
   // this is an obscure case.
   if(signature->common.return_reference && signature->type != ZEND_USER_FUNCTION)
   {
      assert (rhs != EG(uninitialized_zval_ptr));
      rhs->is_ref = 1;
      if (saved_refcount != 0)
      {
	 rhs->refcount = saved_refcount;
      }
      rhs->refcount++;
   }
   saved_refcount = 0; // for 'obscure cases'

   

   zval_ptr_dtor (&rhs);
   if(signature->common.return_reference && signature->type != ZEND_USER_FUNCTION)
      zval_ptr_dtor (&rhs);

phc_check_invariants (TSRMLS_C);
}
// $TLE26 = '';
{
        if (local_TLE26 == NULL)
    {
      local_TLE26 = EG (uninitialized_zval_ptr);
      local_TLE26->refcount++;
    }
  zval** p_lhs = &local_TLE26;

   zval* value;
   if ((*p_lhs)->is_ref)
   {
     // Always overwrite the current value
     value = *p_lhs;
     zval_dtor (value);
   }
   else
   {
     ALLOC_INIT_ZVAL (value);
     zval_ptr_dtor (p_lhs);
     *p_lhs = value;
   }

   ZVAL_STRINGL(value, "", 0, 1);

phc_check_invariants (TSRMLS_C);
}
// return $TLE26;
{
     zval* rhs;
  if (local_TLE26 == NULL)
    rhs = EG (uninitialized_zval_ptr);
  else
    rhs = local_TLE26;

   // Run-time return by reference has different semantics to compile-time.
   // If the function has CTRBR and RTRBR, the the assignment will be
   // reference. If one or the other is return-by-copy, the result will be
   // by copy. Its a question of whether its separated at return-time (which
   // we do here) or at the call-site.
   return_value->value = rhs->value;
   return_value->type = rhs->type;
   zval_copy_ctor (return_value);
   goto end_of_function;
phc_check_invariants (TSRMLS_C);
}
// Method exit
end_of_function:__attribute__((unused));
if (local_TEF4 != NULL)
{
zval_ptr_dtor (&local_TEF4);
}
if (local_TLE17 != NULL)
{
zval_ptr_dtor (&local_TLE17);
}
if (local_TLE18 != NULL)
{
zval_ptr_dtor (&local_TLE18);
}
if (local_TLE19 != NULL)
{
zval_ptr_dtor (&local_TLE19);
}
if (local_TLE20 != NULL)
{
zval_ptr_dtor (&local_TLE20);
}
if (local_TLE21 != NULL)
{
zval_ptr_dtor (&local_TLE21);
}
if (local_TLE22 != NULL)
{
zval_ptr_dtor (&local_TLE22);
}
if (local_TLE23 != NULL)
{
zval_ptr_dtor (&local_TLE23);
}
if (local_TLE25 != NULL)
{
zval_ptr_dtor (&local_TLE25);
}
if (local_TLE26 != NULL)
{
zval_ptr_dtor (&local_TLE26);
}
if (local_TLE3 != NULL)
{
zval_ptr_dtor (&local_TLE3);
}
if (local_TSt24 != NULL)
{
zval_ptr_dtor (&local_TSt24);
}
if (local_holders != NULL)
{
zval_ptr_dtor (&local_holders);
}
if (local_leadingColon != NULL)
{
zval_ptr_dtor (&local_leadingColon);
}
if (local_markers != NULL)
{
zval_ptr_dtor (&local_markers);
}
if (local_parser != NULL)
{
zval_ptr_dtor (&local_parser);
}
if (local_sortText != NULL)
{
zval_ptr_dtor (&local_sortText);
}
if (local_title != NULL)
{
zval_ptr_dtor (&local_title);
}
if (local_titleText != NULL)
{
zval_ptr_dtor (&local_titleText);
}
if (local_wgContLang != NULL)
{
zval_ptr_dtor (&local_wgContLang);
}
}
// ArgInfo structures (necessary to support compile time pass-by-reference)
ZEND_BEGIN_ARG_INFO_EX(CoreLinkFunctions_register_arg_info, 0, 0, 0)
ZEND_ARG_INFO(0, "parser")
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(CoreLinkFunctions_defaultlinkhook_arg_info, 0, 0, 0)
ZEND_ARG_INFO(0, "parser")
ZEND_ARG_INFO(0, "holders")
ZEND_ARG_INFO(0, "markers")
ZEND_ARG_INFO(0, "title")
ZEND_ARG_INFO(0, "titleText")
ZEND_ARG_INFO(1, "displayText")
ZEND_ARG_INFO(1, "leadingColon")
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(CoreLinkFunctions_categorylinkhook_arg_info, 0, 0, 0)
ZEND_ARG_INFO(0, "parser")
ZEND_ARG_INFO(0, "holders")
ZEND_ARG_INFO(0, "markers")
ZEND_ARG_INFO(0, "title")
ZEND_ARG_INFO(0, "titleText")
ZEND_ARG_INFO(1, "sortText")
ZEND_ARG_INFO(1, "leadingColon")
ZEND_END_ARG_INFO()

static function_entry CoreLinkFunctions_functions[] = {
PHP_ME(CoreLinkFunctions, register, CoreLinkFunctions_register_arg_info, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_ME(CoreLinkFunctions, defaultlinkhook, CoreLinkFunctions_defaultlinkhook_arg_info, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_ME(CoreLinkFunctions, categorylinkhook, CoreLinkFunctions_categorylinkhook_arg_info, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
{ NULL, NULL, NULL }
};
// function __MAIN__()
// {
// }
PHP_FUNCTION(__MAIN__)
{
// Function body
// Method exit
end_of_function:__attribute__((unused));
}
// Module initialization
PHP_MINIT_FUNCTION(app)
{
{
zend_class_entry ce; // temp
zend_class_entry* ce_reg; // once registered, ce_ptr should be used
INIT_CLASS_ENTRY(ce, "CoreLinkFunctions", CoreLinkFunctions_functions);
ce_reg = zend_register_internal_class(&ce TSRMLS_CC);
ce_reg->type &= ~ZEND_INTERNAL_CLASS;
}return SUCCESS;}// ArgInfo structures (necessary to support compile time pass-by-reference)
ZEND_BEGIN_ARG_INFO_EX(app___MAIN___arg_info, 0, 0, 0)
ZEND_END_ARG_INFO()

static function_entry app_functions[] = {
PHP_FE(__MAIN__, app___MAIN___arg_info)
{ NULL, NULL, NULL }
};
// Register the module itself with PHP
zend_module_entry app_module_entry = {
STANDARD_MODULE_HEADER, 
"app",
app_functions,
PHP_MINIT(app), /* MINIT */
NULL, /* MSHUTDOWN */
NULL, /* RINIT */
NULL, /* RSHUTDOWN */
NULL, /* MINFO */
"1.0",
STANDARD_MODULE_PROPERTIES
};
#include <sapi/embed/php_embed.h>
#include <signal.h>

void sighandler(int signum)
{
	switch(signum)
	{
		case SIGABRT:
			printf("SIGABRT received!\n");
			break;
		case SIGSEGV:
			printf("SIGSEGV received!\n");
			break;
		default:
			printf("Unknown signal received!\n");
			break;
	}

	printf("This could be a bug in phc. If you suspect it is, please email\n");
	printf("a bug report to phc-general@phpcompiler.org.\n");
	exit(-1);
}

int
main (int argc, char* argv[])
{
   int phc_exit_status;
   signal(SIGABRT, sighandler);
   signal(SIGSEGV, sighandler);

   TSRMLS_D;
   int dealloc_pools = 1;
   php_embed_init (argc, argv PTSRMLS_CC);
   zend_first_try
   {

      // initialize the phc runtime
      init_runtime();

      // load the compiled extension
      zend_startup_module (&app_module_entry);

      zval main_name;
      ZVAL_STRING (&main_name, "__MAIN__", NULL);

      zval retval;

      // Use standard errors, on stdout
      zend_alter_ini_entry ("report_zend_debug", sizeof("report_zend_debug"), "0", sizeof("0") - 1, PHP_INI_ALL, PHP_INI_STAGE_RUNTIME);
      zend_alter_ini_entry ("display_startup_errors", sizeof("display_startup_errors"), "1", sizeof("1") - 1, PHP_INI_ALL, PHP_INI_STAGE_RUNTIME);

      // initialize all the constants
saved_refcount = 0;

      // call __MAIN__
      int success = call_user_function( 
                   EG (function_table),
                   NULL,
                   &main_name,
                   &retval,
                   0,
                   NULL
                   TSRMLS_CC);

      assert (success == SUCCESS);

      // finalize the runtime
      finalize_runtime();

   }
   zend_catch
   {
		dealloc_pools = 0;
   }
   zend_end_try ();
   if (dealloc_pools)
   {
   }
   phc_exit_status = EG(exit_status);
   php_embed_shutdown (TSRMLS_C);

  return phc_exit_status;
}
